diff --git a/SumasenLibs/excel_lib/sumaexcel/sumaexcel.py b/SumasenLibs/excel_lib/sumaexcel/sumaexcel.py index 43ee627..99d13f1 100644 --- a/SumasenLibs/excel_lib/sumaexcel/sumaexcel.py +++ b/SumasenLibs/excel_lib/sumaexcel/sumaexcel.py @@ -775,7 +775,7 @@ class SumasenExcel: def copy_template_range(self, orig_min_row, orig_min_col, orig_max_row, orig_max_col, target_min_row): """ - テンプレートの範囲をコピーし、マージセルの罫線を正しく設定する + テンプレートの範囲をコピーし、マージセルと罫線を正確に設定する """ try: # マージセルの情報を保存 @@ -800,61 +800,53 @@ class SumasenExcel: 'min_col': min_col, 'max_col': max_col, 'min_row': target_merge_min_row, - 'max_row': target_merge_max_row, - 'source_cell': self.template_sheet.cell(row=min_row, column=min_col) + 'max_row': target_merge_max_row }) # セルをマージ self.current_sheet.merge_cells(target_merge_range) - + # セルの内容とスタイルをコピー row_offset = target_min_row - orig_min_row for row in range(orig_min_row, orig_max_row + 1): for col in range(orig_min_col, orig_max_col + 1): source_cell = self.template_sheet.cell(row=row, column=col) target_cell = self.current_sheet.cell(row=row+row_offset, column=col) - - # 値とスタイルをコピー + + # 値のコピー if source_cell.value is not None: target_cell.value = source_cell.value - - if source_cell.has_style: - target_cell.font = copy(source_cell.font) - target_cell.fill = copy(source_cell.fill) - target_cell.number_format = source_cell.number_format - target_cell.protection = copy(source_cell.protection) - target_cell.alignment = copy(source_cell.alignment) - - # マージセルの罫線を設定 + + # フォーマットのコピー + self.copy_cell_formatting(source_cell, target_cell) + + # マージセルの罫線を再設定 for merge_info in merged_ranges: - source_cell = merge_info['source_cell'] - source_border = source_cell.border - - # マージ範囲内の各セルに罫線を設定 + # マージ範囲の各セルの罫線を設定 for row in range(merge_info['min_row'], merge_info['max_row'] + 1): for col in range(merge_info['min_col'], merge_info['max_col'] + 1): + source_cell = self.template_sheet.cell( + row=row - row_offset, + column=col + ) target_cell = self.current_sheet.cell(row=row, column=col) - # 新しい罫線スタイルを作成 - new_border = copy(source_border) - - # 範囲の端のセルの場合のみ、対応する辺の罫線を設定 - if col == merge_info['min_col']: # 左端 - new_border.left = copy(source_border.left) - if col == merge_info['max_col']: # 右端 - new_border.right = copy(source_border.right) - if row == merge_info['min_row']: # 上端 - new_border.top = copy(source_border.top) - if row == merge_info['max_row']: # 下端 - new_border.bottom = copy(source_border.bottom) - - target_cell.border = new_border - - return {"status": True, "message": "Range copied successfully with merged cell borders"} + # 罫線の再設定 + if source_cell.border: + new_border = Border( + left=copy(source_cell.border.left) if col == merge_info['min_col'] else None, + right=copy(source_cell.border.right) if col == merge_info['max_col'] else None, + top=copy(source_cell.border.top) if row == merge_info['min_row'] else None, + bottom=copy(source_cell.border.bottom) if row == merge_info['max_row'] else None + ) + target_cell.border = new_border + + return {"status": True, "message": "Range copied successfully with borders"} except Exception as e: - logging.error(f"Error copying template range: {str(e)}") + logging.error(f"Error in copy_template_range: {str(e)}") return {"status": False, "message": f"Error copying template range: {str(e)}"} + def verify_merged_cell_borders(self, worksheet, merge_range): """ @@ -1044,6 +1036,7 @@ class SumasenExcel: + def copy_template_to_current(self, orig_range, target_range): try: #print(f"copy_template_to_current : orig_range={orig_range},target_range={target_range}") @@ -1069,6 +1062,27 @@ class SumasenExcel: self.current_sheet.row_dimensions[target_row].height = source_height #print(f"Row(target_row).height = {source_height}") + # Copy cell contents and styles + row_offset = target_min_row - orig_min_row + for row in range(orig_min_row, orig_max_row + 1): + for col in range(orig_min_col, orig_max_col + 1): + source_cell = self.template_sheet.cell(row=row, column=col) + target_cell = self.current_sheet.cell(row=row+row_offset, column=col) + + if source_cell.value: + # Copy value + target_cell.value = source_cell.value + #print(f"({col},{row}) : {target_cell.value}") + # Copy styles + if source_cell.has_style: + target_cell.font = copy(source_cell.font) + target_cell.border = copy(source_cell.border) + target_cell.fill = copy(source_cell.fill) + target_cell.number_format = source_cell.number_format + target_cell.protection = copy(source_cell.protection) + target_cell.alignment = copy(source_cell.alignment) + + # Copy merged cells self.copy_template_range(orig_min_row, orig_min_col, orig_max_row, orig_max_col, target_min_row) @@ -1116,7 +1130,7 @@ class SumasenExcel: # 拡大縮小印刷の設定を正確にコピー self.copy_print_scaling_settings(self.template_sheet, self.current_sheet) - # Copy page setup + # その他ページ設定のコピー target_page_setup = self.current_sheet.page_setup source_page_setup = self.template_sheet.page_setup @@ -1124,9 +1138,6 @@ class SumasenExcel: page_setup_attrs = [ 'orientation', # 印刷の向き 'paperSize', # 用紙サイズ - 'scale', # 拡大縮小率 - 'fitToHeight', # 高さの自動調整 - 'fitToWidth', # 幅の自動調整 'firstPageNumber', # 開始ページ番号 'useFirstPageNumber', # 開始ページ番号の使用 'blackAndWhite', # モノクロ印刷 @@ -1192,26 +1203,6 @@ class SumasenExcel: # 用紙の向きと用紙サイズの検証 self._verify_page_setup() - # Copy cell contents and styles - row_offset = target_min_row - orig_min_row - for row in range(orig_min_row, orig_max_row + 1): - for col in range(orig_min_col, orig_max_col + 1): - source_cell = self.template_sheet.cell(row=row, column=col) - target_cell = self.current_sheet.cell(row=row+row_offset, column=col) - - if source_cell.value: - # Copy value - target_cell.value = source_cell.value - #print(f"({col},{row}) : {target_cell.value}") - # Copy styles - if source_cell.has_style: - target_cell.font = copy(source_cell.font) - target_cell.border = copy(source_cell.border) - target_cell.fill = copy(source_cell.fill) - target_cell.number_format = source_cell.number_format - target_cell.protection = copy(source_cell.protection) - target_cell.alignment = copy(source_cell.alignment) - return {"status": True, "message": "Successfully copied template range"} @@ -1219,37 +1210,72 @@ class SumasenExcel: logging.error(f"Error in copy_template_to_current: {str(e)}") return {"status": False, "message": f"Exception in copy_template_to_current: {str(e)}"} - def _verify_page_setup(self): + def _verify_print_settings(self): """ - ページ設定が正しくコピーされたことを検証する + 印刷設定が正しくコピーされたことを検証する """ try: - # 用紙の向きの検証 - if self.template_sheet.page_setup.orientation != self.current_sheet.page_setup.orientation: + source_setup = self.template_sheet.page_setup + target_setup = self.current_sheet.page_setup + + # 拡大縮小設定の検証 + if source_setup.fitToPage != target_setup.fitToPage: logging.warning( - f"Page orientation mismatch: template={self.template_sheet.page_setup.orientation}, " - f"current={self.current_sheet.page_setup.orientation}" + f"fitToPage setting mismatch: template={source_setup.fitToPage}, " + f"current={target_setup.fitToPage}" ) - # 用紙サイズの検証 - if self.template_sheet.page_setup.paperSize != self.current_sheet.page_setup.paperSize: - logging.warning( - f"Paper size mismatch: template={self.template_sheet.page_setup.paperSize}, " - f"current={self.current_sheet.page_setup.paperSize}" - ) - - # 余白設定の検証 - margin_attrs = ['left', 'right', 'top', 'bottom', 'header', 'footer'] - for attr in margin_attrs: - template_margin = getattr(self.template_sheet.page_margins, attr) - current_margin = getattr(self.current_sheet.page_margins, attr) - if abs(template_margin - current_margin) > 0.01: # 小数点の誤差を考慮 + if source_setup.fitToPage: + # 「次のページに合わせる」設定の検証 + if source_setup.fitToWidth != target_setup.fitToWidth: logging.warning( - f"Margin {attr} mismatch: template={template_margin}, current={current_margin}" + f"fitToWidth setting mismatch: template={source_setup.fitToWidth}, " + f"current={target_setup.fitToWidth}" ) + if source_setup.fitToHeight != target_setup.fitToHeight: + logging.warning( + f"fitToHeight setting mismatch: template={source_setup.fitToHeight}, " + f"current={target_setup.fitToHeight}" + ) + elif source_setup.scale != target_setup.scale: + logging.warning( + f"scale setting mismatch: template={source_setup.scale}, " + f"current={target_setup.scale}" + ) + + # 罫線の検証(サンプリング) + self._verify_borders() except Exception as e: - logging.error(f"Error in _verify_page_setup: {str(e)}") + logging.error(f"Error in _verify_print_settings: {str(e)}") + +def _verify_borders(self): + """ + 罫線が正しくコピーされているか検証する + """ + try: + # サンプリングで罫線をチェック + for row in self.current_sheet.iter_rows(min_row=1, max_row=10): + for cell in row: + if cell.border: + # 対応するテンプレートのセルを取得 + template_cell = self.template_sheet.cell( + row=cell.row, + column=cell.column + ) + + # 罫線の設定を比較 + if template_cell.border: + if (template_cell.border.left != cell.border.left or + template_cell.border.right != cell.border.right or + template_cell.border.top != cell.border.top or + template_cell.border.bottom != cell.border.bottom): + logging.warning( + f"Border mismatch at cell {cell.coordinate}" + ) + + except Exception as e: + logging.error(f"Error in _verify_borders: {str(e)}") # Style operations def apply_style(