From b6a866289a24b4d2e16fe2e6101be306fa390739 Mon Sep 17 00:00:00 2001 From: fuzhongyun <15339891972@163.com> Date: Wed, 31 Dec 2025 09:05:28 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E5=AE=9E=E7=BA=BF?= =?UTF-8?q?=E8=BE=B9=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/renderer.py | 40 ++++++++++++++++++++++++++++++++++++++-- tests/test_border.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 tests/test_border.py diff --git a/core/renderer.py b/core/renderer.py index 2bbca5c..6709e74 100644 --- a/core/renderer.py +++ b/core/renderer.py @@ -165,8 +165,44 @@ class ExcelRenderer: # Draw background and border # Scale border width: at least 1px, roughly 1px per scale unit but kept thin for aesthetics - border_width = max(1, scale) - draw.rectangle([x1, y1, x2, y2], fill=bg_color, outline=(200, 200, 200), width=border_width) + default_border_width = max(1, scale) + + # Draw background + draw.rectangle([x1, y1, x2, y2], fill=bg_color) + + # Handle borders + # Default thin grey border if no specific border is set (or for gridlines) + # Note: OpenPyXL borders are complex. We'll simplify: check each side. + + border_color = (200, 200, 200) # Default gridline color + + if cell.border: + # Helper to draw a side + def draw_side(side_obj, coords): + if side_obj and side_obj.style: + # Parse color if available, else default black for set borders + b_color = (0, 0, 0) + if side_obj.color: + b_color = self._parse_color(side_obj.color, default=(0, 0, 0)) + + # Determine width based on style + # 'thin', 'medium', 'thick', 'double', 'hair', 'dashed', 'dotted' + width = default_border_width + if side_obj.style in ['medium', 'thick', 'double']: + width = default_border_width * 2 + + draw.line(coords, fill=b_color, width=width) + else: + # Draw default gridline + draw.line(coords, fill=border_color, width=default_border_width) + + draw_side(cell.border.left, [x1, y1, x1, y2]) + draw_side(cell.border.right, [x2, y1, x2, y2]) + draw_side(cell.border.top, [x1, y1, x2, y1]) + draw_side(cell.border.bottom, [x1, y2, x2, y2]) + else: + # Fallback to simple rectangle outline + draw.rectangle([x1, y1, x2, y2], outline=border_color, width=default_border_width) # Content cell_value = cell.value diff --git a/tests/test_border.py b/tests/test_border.py new file mode 100644 index 0000000..305e44d --- /dev/null +++ b/tests/test_border.py @@ -0,0 +1,36 @@ +import pytest +import io +import os +from core.renderer import ExcelRenderer +from PIL import Image + +# Use the file provided by the user for reproduction +TEST_FILE_PATH = "tests/kshj_gt1767081783800.xlsx" + +@pytest.mark.skipif(not os.path.exists(TEST_FILE_PATH), reason="Test file not found") +def test_border_rendering_real_file(): + """ + Test rendering with a real file that has border issues. + This test will generate an output image for visual inspection. + """ + with open(TEST_FILE_PATH, "rb") as f: + content = f.read() + + renderer = ExcelRenderer(content) + + try: + # Render with high DPI scale + img_bytes = renderer.render_to_bytes(scale=3) + + # Save for visual inspection + output_path = "tests/test_output_border.png" + with open(output_path, "wb") as f_out: + f_out.write(img_bytes) + + print(f"Generated test image at: {os.path.abspath(output_path)}") + + assert isinstance(img_bytes, bytes) + assert len(img_bytes) > 0 + + except Exception as e: + pytest.fail(f"Rendering failed: {e}")