diff --git a/account_statement_import_txt_xlsx/models/account_statement_import_sheet_mapping.py b/account_statement_import_txt_xlsx/models/account_statement_import_sheet_mapping.py
index a0a9e26fba..2a1a181bf4 100644
--- a/account_statement_import_txt_xlsx/models/account_statement_import_sheet_mapping.py
+++ b/account_statement_import_txt_xlsx/models/account_statement_import_sheet_mapping.py
@@ -157,7 +157,18 @@ class AccountStatementImportSheetMapping(models.Model):
string="Bank Account column",
help="Partner's bank account",
)
-
+ footer_lines_skip_count = fields.Integer(
+ string="Footer lines skip count",
+ help="Set the Footer lines number."
+ "Used in some csv/xlsx file that integrate meta data in"
+ "last lines.",
+ default="0",
+ )
+ header_lines_skip_count = fields.Integer(
+ string="Header lines skip count",
+ help="Set the Header lines number.",
+ default="0",
+ )
_sql_constraints = [
(
"check_amount_columns",
diff --git a/account_statement_import_txt_xlsx/models/account_statement_import_sheet_parser.py b/account_statement_import_txt_xlsx/models/account_statement_import_sheet_parser.py
index 1d56b6ab87..22b1a56952 100644
--- a/account_statement_import_txt_xlsx/models/account_statement_import_sheet_parser.py
+++ b/account_statement_import_txt_xlsx/models/account_statement_import_sheet_parser.py
@@ -4,6 +4,7 @@
import itertools
import logging
+from collections.abc import Iterable
from datetime import datetime
from decimal import Decimal
from io import StringIO
@@ -36,21 +37,24 @@ class AccountStatementImportSheetParser(models.TransientModel):
_description = "Bank Statement Import Sheet Parser"
@api.model
- def parse_header(self, data_file, encoding, csv_options):
+ def parse_header(self, data_file, encoding, csv_options, header_lines_skip_count=0):
try:
workbook = xlrd.open_workbook(
file_contents=data_file,
encoding_override=encoding if encoding else None,
)
sheet = workbook.sheet_by_index(0)
- values = sheet.row_values(0)
+ values = sheet.row_values(header_lines_skip_count - 1)
return [str(value) for value in values]
except xlrd.XLRDError:
pass
data = StringIO(data_file.decode(encoding or "utf-8"))
csv_data = reader(data, **csv_options)
- return list(next(csv_data))
+ csv_data_lst = list(csv_data)
+ header = [value.strip() for value in csv_data_lst[header_lines_skip_count - 1]]
+ return header
+ # return list(next(csv_data))
@api.model
def parse(self, data_file, mapping, filename):
@@ -95,7 +99,11 @@ def parse(self, data_file, mapping, filename):
def _get_column_indexes(self, header, column_name, mapping):
column_indexes = []
- if mapping[column_name] and "," in mapping[column_name]:
+ if (
+ mapping[column_name]
+ and isinstance(mapping[column_name], Iterable)
+ and "," in mapping[column_name]
+ ):
# We have to concatenate the values
column_names_or_indexes = mapping[column_name].split(",")
else:
@@ -169,10 +177,10 @@ def _parse_lines(self, mapping, data_file, currency_code):
csv_or_xlsx = reader(StringIO(decoded_file), **csv_options)
header = False
if not mapping.no_header:
+ header_line = mapping.header_lines_skip_count - 1
if isinstance(csv_or_xlsx, tuple):
header = [
- str(value)
- for value in csv_or_xlsx[1].row_values(mapping.offset_row)
+ str(value) for value in csv_or_xlsx[1].row_values(header_line)
]
else:
header = [value.strip() for value in next(csv_or_xlsx)]
@@ -182,7 +190,9 @@ def _parse_lines(self, mapping, data_file, currency_code):
columns[column_name] = self._get_column_indexes(
header, column_name, mapping
)
- return self._parse_rows(mapping, currency_code, csv_or_xlsx, columns)
+ return self._parse_rows(
+ mapping, currency_code, csv_or_xlsx, columns, data_file=data_file
+ )
def _get_values_from_column(self, values, columns, column_name):
indexes = columns[column_name]
@@ -324,25 +334,40 @@ def _decimal(column_name):
line["bank_account"] = bank_account
return line
- def _parse_rows(self, mapping, currency_code, csv_or_xlsx, columns): # noqa: C901
+ def _parse_rows(
+ self, mapping, currency_code, csv_or_xlsx, columns, data_file=None
+ ): # noqa: C901
+ # csv_or_xlsx, data_file = data
+
+ # Get the numbers of rows of the file
+ if isinstance(csv_or_xlsx, tuple):
+ numrows = csv_or_xlsx[1].nrows
+ else:
+ numrows = len(str(data_file.strip()).split("\\n"))
+
+ label_line = mapping.header_lines_skip_count
+ footer_line = numrows - mapping.footer_lines_skip_count
+
if isinstance(csv_or_xlsx, tuple):
- rows = range(mapping.offset_row + 1, csv_or_xlsx[1].nrows)
+ rows = range(mapping.header_lines_skip_count, footer_line)
else:
rows = csv_or_xlsx
lines = []
- for row in rows:
+ for index, row in enumerate(rows, label_line):
if isinstance(csv_or_xlsx, tuple):
book = csv_or_xlsx[0]
sheet = csv_or_xlsx[1]
values = []
- for col_index in range(mapping.offset_column, sheet.row_len(row)):
+ for col_index in range(0, sheet.row_len(row)):
cell_type = sheet.cell_type(row, col_index)
cell_value = sheet.cell_value(row, col_index)
if cell_type == xlrd.XL_CELL_DATE:
cell_value = xldate_as_datetime(cell_value, book.datemode)
values.append(cell_value)
else:
+ if index >= footer_line:
+ continue
values = list(row)
if mapping.skip_empty_lines and not any(values):
continue
diff --git a/account_statement_import_txt_xlsx/views/account_statement_import_sheet_mapping.xml b/account_statement_import_txt_xlsx/views/account_statement_import_sheet_mapping.xml
index 0ab58c800d..afe6a70593 100644
--- a/account_statement_import_txt_xlsx/views/account_statement_import_sheet_mapping.xml
+++ b/account_statement_import_txt_xlsx/views/account_statement_import_sheet_mapping.xml
@@ -72,6 +72,10 @@
attrs="{'required': [('debit_credit_column', '!=', False)]}"
/>
+
+
+
+