|
4 | 4 | セル範囲の計算・変換・検証を担当するヘルパークラス |
5 | 5 | """ |
6 | 6 |
|
| 7 | +import logging |
| 8 | + |
7 | 9 | from openpyxl.utils import column_index_from_string, get_column_letter |
8 | 10 | from openpyxl.utils.cell import coordinate_from_string |
9 | 11 |
|
| 12 | +logger = logging.getLogger(__name__) |
| 13 | + |
10 | 14 |
|
11 | 15 | class ExcelRangeCalculator: |
12 | 16 | """セル範囲の計算・変換・検証(全て staticmethod)""" |
@@ -127,7 +131,7 @@ def expand_axis_range(range_str: str) -> str: |
127 | 131 | try: |
128 | 132 | col, row = coordinate_from_string(raw.replace("$", "")) |
129 | 133 | return f"{col}1:{col}{row}" |
130 | | - except Exception: |
| 134 | + except ValueError: |
131 | 135 | return range_str |
132 | 136 |
|
133 | 137 | start_cell, end_cell = raw.split(":", 1) |
@@ -160,33 +164,36 @@ def calculate_range_size(range_str: str) -> tuple[int, int]: |
160 | 164 | range_str: セル範囲(例: "A1:D10" または "A1:XFD1048576") |
161 | 165 |
|
162 | 166 | Returns: |
163 | | - (rows, cols)のタプル |
164 | | -
|
165 | | - Raises: |
166 | | - ValueError: 逆順序の範囲を検出した場合 |
| 167 | + (rows, cols)のタプル。 |
| 168 | + エラー時は (0, 0) を返す。 |
167 | 169 | """ |
168 | | - if ":" not in range_str: |
169 | | - # 単一セルの場合 |
170 | | - return (1, 1) |
171 | | - |
172 | | - start_cell, end_cell = range_str.split(":") |
173 | | - start_col, start_row = coordinate_from_string(start_cell) |
174 | | - end_col, end_row = coordinate_from_string(end_cell) |
175 | | - |
176 | | - start_col_idx = column_index_from_string(start_col) |
177 | | - end_col_idx = column_index_from_string(end_col) |
178 | | - |
179 | | - # 逆順序の範囲を検出(セキュリティ対策) |
180 | | - if end_row < start_row or end_col_idx < start_col_idx: |
181 | | - raise ValueError( |
182 | | - f"無効なセル範囲: '{range_str}'。" |
183 | | - f"範囲は正しい順序で指定してください(例: 'A1:Z100')" |
184 | | - ) |
185 | | - |
186 | | - rows = end_row - start_row + 1 |
187 | | - cols = end_col_idx - start_col_idx + 1 |
188 | | - |
189 | | - return (rows, cols) |
| 170 | + try: |
| 171 | + if ":" not in range_str: |
| 172 | + # 単一セルの場合 |
| 173 | + return (1, 1) |
| 174 | + |
| 175 | + start_cell, end_cell = range_str.split(":") |
| 176 | + start_col, start_row = coordinate_from_string(start_cell) |
| 177 | + end_col, end_row = coordinate_from_string(end_cell) |
| 178 | + |
| 179 | + start_col_idx = column_index_from_string(start_col) |
| 180 | + end_col_idx = column_index_from_string(end_col) |
| 181 | + |
| 182 | + # 逆順序の範囲を検出(セキュリティ対策) |
| 183 | + if end_row < start_row or end_col_idx < start_col_idx: |
| 184 | + raise ValueError( |
| 185 | + f"無効なセル範囲: '{range_str}'。" |
| 186 | + f"範囲は正しい順序で指定してください(例: 'A1:Z100')" |
| 187 | + ) |
| 188 | + |
| 189 | + rows = end_row - start_row + 1 |
| 190 | + cols = end_col_idx - start_col_idx + 1 |
| 191 | + |
| 192 | + return (rows, cols) |
| 193 | + except Exception as e: |
| 194 | + # 元の実装との互換性維持: エラー時は (0, 0) を返す |
| 195 | + logger.warning(f"Failed to calculate range size '{range_str}': {e}") |
| 196 | + return (0, 0) |
190 | 197 |
|
191 | 198 | @staticmethod |
192 | 199 | def normalize_column_range(cell_range: str, max_row: int) -> str: |
|
0 commit comments