diff --git a/parser_2gis/gui/settings.py b/parser_2gis/gui/settings.py index c268212..9a86926 100644 --- a/parser_2gis/gui/settings.py +++ b/parser_2gis/gui/settings.py @@ -146,6 +146,20 @@ def gui_settings(config: Configuration) -> None: default=config.writer.csv.remove_duplicates, checkbox_color=sg.theme_input_background_color(), enable_events=True), ], + [ + sg.Column([ + [ + sg.Text('Разделитель CSV'), + ] + ], expand_x=True, pad=0), + sg.Column([ + [ + sg.Input(size=(3, 1), justification='center', key='-WRITER.CSV.DELIMITER-', + tooltip='Символ-разделитель колонок в CSV.', + default_text = config.writer.csv.delimiter), + ], + ], element_justification='right', pad=0), + ], [ sg.Column([ [ diff --git a/parser_2gis/writer/options.py b/parser_2gis/writer/options.py index bcdcd96..d5b1c8d 100644 --- a/parser_2gis/writer/options.py +++ b/parser_2gis/writer/options.py @@ -16,6 +16,7 @@ class CSVOptions(BaseModel): remove_empty_columns: Remove empty columns after parsing process finished. remove_duplicates: Remove duplicates after parsing process finished. join_char: Char for joining complex values. + delimiter: CSV char-delimiter """ add_rubrics: bool = True add_comments: bool = True @@ -23,6 +24,7 @@ class CSVOptions(BaseModel): remove_empty_columns: bool = True remove_duplicates: bool = True join_char: str = '; ' + delimiter: str = ',' class WriterOptions(BaseModel): diff --git a/parser_2gis/writer/writers/csv_writer.py b/parser_2gis/writer/writers/csv_writer.py index 5b90161..977d71f 100644 --- a/parser_2gis/writer/writers/csv_writer.py +++ b/parser_2gis/writer/writers/csv_writer.py @@ -16,6 +16,15 @@ class CSVWriter(FileWriter): """Writer to CSV table.""" + @property + def _dialect(self) -> csv.Dialect: + class CustomDialect(csv.Dialect): + delimiter = self._options.csv.delimiter + quoting = csv.QUOTE_MINIMAL + lineterminator = "\n" + quotechar= '"' + return CustomDialect + @property def _type_names(self) -> dict[str, str]: return { @@ -76,7 +85,7 @@ def _writerow(self, row: dict[str, Any]) -> None: def __enter__(self) -> CSVWriter: super().__enter__() - self._writer = csv.DictWriter(self._file, self._data_mapping.keys()) + self._writer = csv.DictWriter(self._file, self._data_mapping.keys(), dialect=self._dialect) self._writer.writerow(self._data_mapping) # Write header self._wrote_count = 0 return self @@ -98,9 +107,9 @@ def _remove_empty_columns(self) -> None: # Looking for empty columns with self._open_file(self._file_path, 'r') as f_csv: - csv_reader = csv.DictReader(f_csv, self._data_mapping.keys()) # type: ignore + csv_reader = csv.DictReader(f_csv, self._data_mapping.keys(), dialect=self._dialect) # type: ignore next(csv_reader, None) # Skip header - for row in csv.DictReader(f_csv, self._data_mapping.keys()): # type: ignore + for row in csv.DictReader(f_csv, self._data_mapping.keys(), dialect=self._dialect): # type: ignore for column_name in complex_columns_count.keys(): if row[column_name] != '': complex_columns_count[column_name] += 1 @@ -124,8 +133,8 @@ def _remove_empty_columns(self) -> None: with self._open_file(tmp_csv_name, 'w') as f_tmp_csv, \ self._open_file(self._file_path, 'r') as f_csv: - csv_writer = csv.DictWriter(f_tmp_csv, new_data_mapping.keys()) # type: ignore - csv_reader = csv.DictReader(f_csv, self._data_mapping.keys()) # type: ignore + csv_writer = csv.DictWriter(f_tmp_csv, new_data_mapping.keys(), dialect=self._dialect) # type: ignore + csv_reader = csv.DictReader(f_csv, self._data_mapping.keys(), dialect=self._dialect) # type: ignore csv_writer.writerow(new_data_mapping) # Write new header next(csv_reader, None) # Skip header