Hashavshevet is the most widely-used accounting software in Israel, but it operates in a desktop environment with proprietary formats. Transferring data from Hashavshevet to modern systems or importing data into it requires complex conversions, including handling Hebrew encoding (Windows-1255).
Author: @skills-il
Import and export data between Hashavshevet accounting software and modern formats like JSON, CSV, and Excel, including Hebrew encoding conversion and cloud migration
npx skills-il add skills-il/accounting --skill hashavshevet-data-toolsDetermine which version of Hashavshevet the user is working with and identify the relevant file formats:
.hsh proprietary binary format and fixed-width text exports (.dat, .txt).mdb (Access) or .accdb databases, with CSV/fixed-width export capabilityCommon Hashavshevet data files:
| File / Table | Hebrew Name | Description | Typical Format |
|---|---|---|---|
HESHIN.dat |
מאזן חשבונות | Chart of accounts | Fixed-width, Windows-1255 |
PKUDOT.dat |
פקודות יומן | Journal entries | Fixed-width, Windows-1255 |
MANOT.dat |
מנות | Batches | Fixed-width, Windows-1255 |
KARTIS.dat |
כרטיסי חשבון | Account cards / ledger | Fixed-width, Windows-1255 |
HESHBON.dat |
חשבונות | Account master list | Fixed-width, Windows-1255 |
MATZAV.dat |
מצב חשבון | Account balances | Fixed-width, Windows-1255 |
TNUOT.dat |
תנועות | Transactions | Fixed-width, Windows-1255 |
Hashavshevet files typically use Windows-1255 (Hebrew) encoding. Convert to UTF-8 before processing:
import chardet
def detect_and_convert(file_path: str) -> str:
"""Detect encoding and convert Hashavshevet file to UTF-8."""
with open(file_path, 'rb') as f:
raw_data = f.read()
detected = chardet.detect(raw_data)
encoding = detected['encoding']
# Hashavshevet almost always uses Windows-1255
if encoding and encoding.lower() in ('windows-1255', 'iso-8859-8', 'hebrew'):
encoding = 'windows-1255'
elif encoding is None:
encoding = 'windows-1255' # Safe fallback for Hebrew accounting data
return raw_data.decode(encoding, errors='replace')Common encoding pitfalls:
Hashavshevet .dat files use fixed-width column layouts. The column widths vary by file type:
# HESHIN.dat (Chart of Accounts) column layout
HESHIN_COLUMNS = {
'account_number': (0, 15), # מספר חשבון
'account_name': (15, 65), # שם חשבון
'account_type': (65, 67), # סוג חשבון (1=asset, 2=liability, 3=equity, 4=income, 5=expense)
'parent_account': (67, 82), # חשבון אב
'sort_code': (82, 92), # קוד מיון
'is_active': (92, 93), # פעיל (1=yes, 0=no)
'opening_balance': (93, 113), # יתרת פתיחה
'currency': (113, 116), # מטבע
}
# PKUDOT.dat (Journal Entries) column layout
PKUDOT_COLUMNS = {
'entry_number': (0, 10), # מספר פקודה
'batch_number': (10, 18), # מספר מנה
'entry_date': (18, 28), # תאריך (DD/MM/YYYY)
'account_debit': (28, 43), # חשבון חובה
'account_credit': (43, 58), # חשבון זכות
'amount': (58, 73), # סכום
'currency': (73, 76), # מטבע
'reference': (76, 96), # אסמכתא
'description': (96, 146), # תיאור
'value_date': (146, 156), # תאריך ערך
}Parse these files using the column positions:
def parse_fixed_width(content: str, columns: dict) -> list[dict]:
"""Parse a fixed-width Hashavshevet data file."""
records = []
for line in content.strip().split('\n'):
if not line.strip():
continue
record = {}
for field_name, (start, end) in columns.items():
value = line[start:end].strip() if len(line) > start else ''
record[field_name] = value
records.append(record)
return recordsConvert parsed Hashavshevet data to JSON, CSV, or Excel:
import csv
import json
def export_to_csv(records: list[dict], output_path: str):
"""Export parsed records to UTF-8 CSV with BOM for Excel compatibility."""
if not records:
return
with open(output_path, 'w', encoding='utf-8-sig', newline='') as f:
writer = csv.DictWriter(f, fieldnames=records[0].keys())
writer.writeheader()
writer.writerows(records)
def export_to_json(records: list[dict], output_path: str):
"""Export parsed records to JSON with Hebrew support."""
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(records, f, ensure_ascii=False, indent=2)
def export_to_excel(records: list[dict], output_path: str, sheet_name: str = 'Data'):
"""Export parsed records to Excel with proper RTL formatting."""
from openpyxl import Workbook
from openpyxl.worksheet.properties import WorksheetProperties
wb = Workbook()
ws = wb.active
ws.title = sheet_name
ws.sheet_properties = WorksheetProperties(rightToLeft=True)
# Write headers
headers = list(records[0].keys())
for col, header in enumerate(headers, 1):
ws.cell(row=1, column=col, value=header)
# Write data
for row_idx, record in enumerate(records, 2):
for col_idx, header in enumerate(headers, 1):
ws.cell(row=row_idx, column=col_idx, value=record.get(header, ''))
wb.save(output_path)When importing data into Hashavshevet, generate fixed-width files matching the expected layout:
def generate_hashavshevet_import(records: list[dict], columns: dict, output_path: str):
"""Generate a fixed-width file for Hashavshevet import."""
lines = []
for record in records:
line = ''
sorted_cols = sorted(columns.items(), key=lambda x: x[1][0])
for field_name, (start, width_end) in sorted_cols:
width = width_end - start
value = str(record.get(field_name, ''))
# Pad or truncate to exact width
if len(value) > width:
value = value[:width]
else:
value = value.ljust(width)
line += value
lines.append(line)
with open(output_path, 'w', encoding='windows-1255', errors='replace') as f:
f.write('\n'.join(lines))Import validation rules:
When migrating from Hashavshevet to cloud-based accounting solutions:
iCount migration:
Rivhit migration:
Invoice4U migration:
After any import or export operation, validate data integrity:
def validate_trial_balance(records: list[dict]) -> dict:
"""Validate that debits equal credits in journal entries."""
total_debit = 0
total_credit = 0
errors = []
for i, record in enumerate(records):
try:
amount = float(record.get('amount', 0))
if record.get('account_debit'):
total_debit += amount
if record.get('account_credit'):
total_credit += amount
except ValueError:
errors.append(f"Row {i+1}: Invalid amount '{record.get('amount')}'")
balanced = abs(total_debit - total_credit) < 0.01
return {
'balanced': balanced,
'total_debit': round(total_debit, 2),
'total_credit': round(total_credit, 2),
'difference': round(total_debit - total_credit, 2),
'errors': errors,
}
def validate_account_references(entries: list[dict], accounts: list[dict]) -> list[str]:
"""Verify all referenced accounts exist in the chart of accounts."""
valid_accounts = {a['account_number'] for a in accounts}
errors = []
for i, entry in enumerate(entries):
debit_acc = entry.get('account_debit', '').strip()
credit_acc = entry.get('account_credit', '').strip()
if debit_acc and debit_acc not in valid_accounts:
errors.append(f"Row {i+1}: Debit account '{debit_acc}' not found in chart of accounts")
if credit_acc and credit_acc not in valid_accounts:
errors.append(f"Row {i+1}: Credit account '{credit_acc}' not found in chart of accounts")
return errorsUser says: "I have a PKUDOT.dat file from Hashavshevet Gold. I need to export all journal entries from 2025 to an Excel file for my auditor."
Actions:
PKUDOT.dat file and detect encoding (Windows-1255)entry_date falls within 01/01/2025 to 31/12/2025Result: An Excel file pkudot_2025.xlsx with all 2025 journal entries, properly formatted with Hebrew headers, RTL sheet direction, and a validation summary confirming the trial balance is balanced.
User says: "I downloaded bank transactions from Leumi as a CSV. I need to convert them into a format I can import into Hashavshevet 2000+."
Actions:
entry_date, description to description, amount to amount, reference number to reference.dat file in Windows-1255 encodingResult: A bank_import.dat file ready for import into Hashavshevet 2000+, with 47 transactions properly formatted, encoded in Windows-1255, and validated.
User says: "We're moving from Hashavshevet Gold to Rivhit. I need to export our chart of accounts and opening balances in a format Rivhit can import."
Actions:
HESHIN.dat (chart of accounts) and MATZAV.dat (account balances) from HashavshevetResult: A Rivhit-compatible Excel import file with 234 accounts, a mapping reference document, and a summary of 12 accounts that need manual review due to type classification differences.
scripts/encoding_converter.py -- Batch convert Hashavshevet files from Windows-1255 to UTF-8. Run: python scripts/encoding_converter.py --helpscripts/dat_parser.py -- Parse Hashavshevet fixed-width .dat files to JSON/CSV. Run: python scripts/dat_parser.py --helpreferences/hashavshevet-file-formats.md -- Detailed column layouts for all Hashavshevet .dat file types. Consult when encountering an unfamiliar file type or when column positions seem incorrect.references/cloud-migration-mappings.md -- Account type and field mappings for iCount, Rivhit, and Invoice4U migrations. Consult when planning a migration to a cloud-based solution.Cause: The file is encoded in Windows-1255 (Hebrew) but is being read as UTF-8. This is the most common error when working with Hashavshevet files, as the software uses Windows-1255 by default.
Solution: Explicitly specify encoding='windows-1255' when reading the file. If unsure about the encoding, use the chardet library to auto-detect it. For files with mixed encoding, use errors='replace' to substitute undecodable characters.
Cause: Rounding differences from currency conversions, partial exports (missing entries from a batch), or corrupted data in the source file. Hashavshevet sometimes stores amounts with extra decimal places internally. Solution: First check if the difference is a small rounding error (less than 1 ILS). If so, create an adjustment entry. For larger differences, verify the export includes all batches for the period. Re-export from Hashavshevet using the "full export" option rather than filtered export.
Cause: Journal entries reference accounts that were deleted or renumbered in Hashavshevet, or the chart of accounts export is from a different fiscal year than the journal entries. Solution: Export both the chart of accounts and journal entries from the same Hashavshevet database and fiscal year. If accounts were renumbered, create a mapping table and update references before import. Check for leading zeros being stripped during conversion.
Cause: Hashavshevet expects DD/MM/YYYY (Israeli format) but the source data uses MM/DD/YYYY (American format) or YYYY-MM-DD (ISO format). This commonly occurs when importing bank data or data from international systems. Solution: Normalize all dates to DD/MM/YYYY before generating the import file. Check for ambiguous dates where day and month could be swapped (e.g., 03/04/2025 could be March 4 or April 3) and verify against the source system's format.
Supported Agents
Export all journal entries from Hashavshevet to CSV format with UTF-8 encoding.
Prepare a migration plan from Hashavshevet to iCount, including chart of accounts mapping and integrity checks.
Fix the encoding of a Hashavshevet file that shows garbled Hebrew text.
Trust Score
This skill can execute scripts and commands on your system.
1 occurrences found in code
This skill can read and write files on your system.
1 occurrences found in code
Build SHAAM-compliant electronic invoices with allocation numbers per Israeli Tax Authority requirements
OCR and parse Israeli receipts and invoices with Hebrew and English text extraction
Automate bank reconciliation for Israeli banks, including discrepancy detection and reconciliation report generation
Want to build your own skill? Try the Skill Creator · Submit a Skill