diff --git a/sync_manager.py b/sync_manager.py index 5dc97f9a..f3b2c9d5 100644 --- a/sync_manager.py +++ b/sync_manager.py @@ -83,9 +83,10 @@ class SyncManager: self.smart_merge_cols = ["CRM Website"] def _load_data(self): - # (Diese Funktion bleibt exakt wie in der letzten Version) + """Lädt und bereitet die Daten aus D365 und Google Sheets vor.""" self.logger.info(f"Lade Daten aus D365-Export: '{self.d365_export_path}'...") try: + # D365 wird bereits typsicher als String geladen, das ist korrekt. temp_d365_df = pd.read_excel(self.d365_export_path, dtype=str).fillna('') for d365_col in self.d365_to_gsheet_map.keys(): if d365_col not in temp_d365_df.columns: @@ -100,19 +101,29 @@ class SyncManager: self.logger.info("Lade bestehende Daten aus dem Google Sheet...") try: - all_data_with_headers = self.sheet_handler.get_all_data_with_headers() + # --- TYPSICHeres LADEN AUS GSHEET --- + # 1. Lade alle Werte mit der Option, sie als rohen TEXT zu formatieren. + all_data_with_headers = self.sheet_handler.sheet.get_all_values(value_render_option='FORMATTED_STRING') + if not all_data_with_headers or len(all_data_with_headers) < self.sheet_handler._header_rows: self.gsheet_df = pd.DataFrame(columns=COLUMN_ORDER).fillna('') else: actual_header = all_data_with_headers[self.sheet_handler._header_rows - 1] data_rows = all_data_with_headers[self.sheet_handler._header_rows:] + temp_df = pd.DataFrame(data_rows) if not temp_df.empty: - if temp_df.shape[1] > len(actual_header): - temp_df = temp_df.iloc[:, :len(actual_header)] + # Spaltenanzahl an Header anpassen + num_cols_to_match = len(actual_header) + if temp_df.shape[1] > num_cols_to_match: + temp_df = temp_df.iloc[:, :num_cols_to_match] + elif temp_df.shape[1] < num_cols_to_match: + for i in range(num_cols_to_match - temp_df.shape[1]): + temp_df[f'temp_{i}'] = '' temp_df.columns = actual_header else: temp_df = pd.DataFrame(columns=actual_header) + temp_df = temp_df.fillna('') for col_name in COLUMN_ORDER: if col_name not in temp_df.columns: