claude-code-hwp-mcp 0.3.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -24
- package/dist/hwp-bridge.js +17 -12
- package/dist/index.js +2 -2
- package/dist/tools/analysis-tools.js +183 -0
- package/dist/tools/editing-tools.js +86 -7
- package/package.json +2 -2
- package/python/hwp_editor.py +276 -71
- package/python/hwp_service.py +429 -42
- package/python/ref_reader.py +167 -2
- package/python/requirements.txt +1 -0
package/python/hwp_editor.py
CHANGED
|
@@ -35,18 +35,30 @@ def insert_text_with_color(hwp, text, rgb=None):
|
|
|
35
35
|
def insert_text_with_style(hwp, text, style=None):
|
|
36
36
|
"""서식 지정 텍스트 삽입.
|
|
37
37
|
style: {
|
|
38
|
-
"color": [r,g,b],
|
|
39
|
-
"bold": True/False,
|
|
40
|
-
"italic": True/False,
|
|
41
|
-
"underline": True/False,
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
38
|
+
"color": [r,g,b], # 글자 색상
|
|
39
|
+
"bold": True/False, # 굵게
|
|
40
|
+
"italic": True/False, # 기울임
|
|
41
|
+
"underline": True/False, # 밑줄 (bool → 실선)
|
|
42
|
+
"underline_type": 0-7, # 밑줄 종류 (0=없음,1=실선,2=이중,3=점선,4=파선,5=1점쇄선,6=물결,7=굵은실선)
|
|
43
|
+
"underline_color": [r,g,b], # 밑줄 색상
|
|
44
|
+
"font_size": 12.0, # 글자 크기 (pt)
|
|
45
|
+
"font_name": "맑은 고딕", # 글꼴 (한글+라틴 동시)
|
|
46
|
+
"font_name_latin": "Arial", # 라틴 전용 글꼴
|
|
47
|
+
"bg_color": [r,g,b], # 배경 색상
|
|
48
|
+
"strikeout": True/False, # 취소선 (bool → 단일)
|
|
49
|
+
"strikeout_type": 0-3, # 취소선 종류 (0=없음,1=단일,2=이중,3=굵은)
|
|
50
|
+
"strikeout_color": [r,g,b], # 취소선 색상
|
|
51
|
+
"char_spacing": -5, # 자간 (%, 기본 0)
|
|
52
|
+
"width_ratio": 90, # 장평 (%, 기본 100)
|
|
53
|
+
"font_name_hanja": "바탕", # 한자 글꼴
|
|
54
|
+
"font_name_japanese": "", # 일본어 글꼴
|
|
55
|
+
"superscript": True/False, # 위 첨자
|
|
56
|
+
"subscript": True/False, # 아래 첨자
|
|
57
|
+
"outline": True/False, # 외곽선
|
|
58
|
+
"shadow": True/False, # 그림자
|
|
59
|
+
"emboss": True/False, # 양각
|
|
60
|
+
"engrave": True/False, # 음각
|
|
61
|
+
"small_caps": True/False, # 작은 대문자
|
|
50
62
|
}
|
|
51
63
|
삽입 후 원래 서식으로 복원.
|
|
52
64
|
"""
|
|
@@ -59,22 +71,20 @@ def insert_text_with_style(hwp, text, style=None):
|
|
|
59
71
|
|
|
60
72
|
# 현재 서식 저장
|
|
61
73
|
act.GetDefault("CharShape", pset.HSet)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
except Exception:
|
|
77
|
-
pass
|
|
74
|
+
saved = {}
|
|
75
|
+
saved['TextColor'] = pset.TextColor
|
|
76
|
+
saved['Bold'] = pset.Bold
|
|
77
|
+
saved['Italic'] = pset.Italic
|
|
78
|
+
saved['UnderlineType'] = pset.UnderlineType
|
|
79
|
+
saved['Height'] = pset.Height
|
|
80
|
+
saved['StrikeOutType'] = pset.StrikeOutType
|
|
81
|
+
for attr in ['SpacingHangul', 'RatioHangul', 'SuperScript', 'SubScript',
|
|
82
|
+
'OutLineType', 'ShadowType', 'Emboss', 'Engrave', 'SmallCaps',
|
|
83
|
+
'UnderlineColor', 'StrikeOutColor']:
|
|
84
|
+
try:
|
|
85
|
+
saved[attr] = getattr(pset, attr)
|
|
86
|
+
except Exception:
|
|
87
|
+
saved[attr] = None
|
|
78
88
|
|
|
79
89
|
# 새 서식 적용
|
|
80
90
|
act.GetDefault("CharShape", pset.HSet)
|
|
@@ -86,18 +96,36 @@ def insert_text_with_style(hwp, text, style=None):
|
|
|
86
96
|
pset.Bold = 1 if style["bold"] else 0
|
|
87
97
|
if "italic" in style:
|
|
88
98
|
pset.Italic = 1 if style["italic"] else 0
|
|
89
|
-
if "
|
|
99
|
+
if "underline_type" in style:
|
|
100
|
+
pset.UnderlineType = int(style["underline_type"])
|
|
101
|
+
elif "underline" in style:
|
|
90
102
|
pset.UnderlineType = 1 if style["underline"] else 0
|
|
103
|
+
if "underline_color" in style:
|
|
104
|
+
uc = style["underline_color"]
|
|
105
|
+
try:
|
|
106
|
+
pset.UnderlineColor = hwp.RGBColor(uc[0], uc[1], uc[2])
|
|
107
|
+
except Exception as e:
|
|
108
|
+
print(f"[WARN] UnderlineColor: {e}", file=sys.stderr)
|
|
91
109
|
if "font_size" in style:
|
|
92
110
|
pset.Height = int(style["font_size"] * 100) # pt → HWP 단위
|
|
93
111
|
if "font_name" in style:
|
|
94
112
|
pset.FaceNameHangul = style["font_name"]
|
|
95
113
|
pset.FaceNameLatin = style["font_name"]
|
|
114
|
+
if "font_name_latin" in style:
|
|
115
|
+
pset.FaceNameLatin = style["font_name_latin"]
|
|
96
116
|
if "bg_color" in style:
|
|
97
117
|
bg = style["bg_color"]
|
|
98
118
|
pset.ShadeColor = hwp.RGBColor(bg[0], bg[1], bg[2])
|
|
99
|
-
if "
|
|
119
|
+
if "strikeout_type" in style:
|
|
120
|
+
pset.StrikeOutType = int(style["strikeout_type"])
|
|
121
|
+
elif "strikeout" in style:
|
|
100
122
|
pset.StrikeOutType = 1 if style["strikeout"] else 0
|
|
123
|
+
if "strikeout_color" in style:
|
|
124
|
+
sc = style["strikeout_color"]
|
|
125
|
+
try:
|
|
126
|
+
pset.StrikeOutColor = hwp.RGBColor(sc[0], sc[1], sc[2])
|
|
127
|
+
except Exception as e:
|
|
128
|
+
print(f"[WARN] StrikeOutColor: {e}", file=sys.stderr)
|
|
101
129
|
if "char_spacing" in style:
|
|
102
130
|
try:
|
|
103
131
|
pset.SpacingHangul = int(style["char_spacing"])
|
|
@@ -120,6 +148,77 @@ def insert_text_with_style(hwp, text, style=None):
|
|
|
120
148
|
pset.FaceNameJapanese = style["font_name_japanese"]
|
|
121
149
|
except Exception as e:
|
|
122
150
|
print(f"[WARN] {e}", file=sys.stderr)
|
|
151
|
+
# 위/아래 첨자
|
|
152
|
+
if "superscript" in style:
|
|
153
|
+
try:
|
|
154
|
+
pset.SuperScript = 1 if style["superscript"] else 0
|
|
155
|
+
except Exception as e:
|
|
156
|
+
print(f"[WARN] SuperScript: {e}", file=sys.stderr)
|
|
157
|
+
if "subscript" in style:
|
|
158
|
+
try:
|
|
159
|
+
pset.SubScript = 1 if style["subscript"] else 0
|
|
160
|
+
except Exception as e:
|
|
161
|
+
print(f"[WARN] SubScript: {e}", file=sys.stderr)
|
|
162
|
+
# 외곽선/그림자/양각/음각/작은대문자
|
|
163
|
+
if "outline" in style:
|
|
164
|
+
try:
|
|
165
|
+
pset.OutLineType = 1 if style["outline"] else 0
|
|
166
|
+
except Exception as e:
|
|
167
|
+
print(f"[WARN] OutLineType: {e}", file=sys.stderr)
|
|
168
|
+
if "shadow" in style:
|
|
169
|
+
try:
|
|
170
|
+
pset.ShadowType = 1 if style["shadow"] else 0
|
|
171
|
+
except Exception as e:
|
|
172
|
+
print(f"[WARN] ShadowType: {e}", file=sys.stderr)
|
|
173
|
+
if "emboss" in style:
|
|
174
|
+
try:
|
|
175
|
+
pset.Emboss = 1 if style["emboss"] else 0
|
|
176
|
+
except Exception as e:
|
|
177
|
+
print(f"[WARN] Emboss: {e}", file=sys.stderr)
|
|
178
|
+
if "engrave" in style:
|
|
179
|
+
try:
|
|
180
|
+
pset.Engrave = 1 if style["engrave"] else 0
|
|
181
|
+
except Exception as e:
|
|
182
|
+
print(f"[WARN] Engrave: {e}", file=sys.stderr)
|
|
183
|
+
if "small_caps" in style:
|
|
184
|
+
try:
|
|
185
|
+
pset.SmallCaps = 1 if style["small_caps"] else 0
|
|
186
|
+
except Exception as e:
|
|
187
|
+
print(f"[WARN] SmallCaps: {e}", file=sys.stderr)
|
|
188
|
+
# 그림자 색상/오프셋
|
|
189
|
+
if "shadow_color" in style:
|
|
190
|
+
try:
|
|
191
|
+
sc = style["shadow_color"]
|
|
192
|
+
pset.ShadowColor = hwp.RGBColor(sc[0], sc[1], sc[2])
|
|
193
|
+
except Exception as e:
|
|
194
|
+
print(f"[WARN] ShadowColor: {e}", file=sys.stderr)
|
|
195
|
+
if "shadow_offset_x" in style:
|
|
196
|
+
try:
|
|
197
|
+
pset.ShadowOffsetX = int(style["shadow_offset_x"])
|
|
198
|
+
except Exception as e:
|
|
199
|
+
print(f"[WARN] ShadowOffsetX: {e}", file=sys.stderr)
|
|
200
|
+
if "shadow_offset_y" in style:
|
|
201
|
+
try:
|
|
202
|
+
pset.ShadowOffsetY = int(style["shadow_offset_y"])
|
|
203
|
+
except Exception as e:
|
|
204
|
+
print(f"[WARN] ShadowOffsetY: {e}", file=sys.stderr)
|
|
205
|
+
# 밑줄/취소선 모양
|
|
206
|
+
if "underline_shape" in style:
|
|
207
|
+
try:
|
|
208
|
+
pset.UnderlineShape = int(style["underline_shape"])
|
|
209
|
+
except Exception as e:
|
|
210
|
+
print(f"[WARN] UnderlineShape: {e}", file=sys.stderr)
|
|
211
|
+
if "strikeout_shape" in style:
|
|
212
|
+
try:
|
|
213
|
+
pset.StrikeOutShape = int(style["strikeout_shape"])
|
|
214
|
+
except Exception as e:
|
|
215
|
+
print(f"[WARN] StrikeOutShape: {e}", file=sys.stderr)
|
|
216
|
+
# 커닝
|
|
217
|
+
if "use_kerning" in style:
|
|
218
|
+
try:
|
|
219
|
+
pset.UseKerning = 1 if style["use_kerning"] else 0
|
|
220
|
+
except Exception as e:
|
|
221
|
+
print(f"[WARN] UseKerning: {e}", file=sys.stderr)
|
|
123
222
|
|
|
124
223
|
act.Execute("CharShape", pset.HSet)
|
|
125
224
|
|
|
@@ -127,24 +226,24 @@ def insert_text_with_style(hwp, text, style=None):
|
|
|
127
226
|
|
|
128
227
|
# 원래 서식 복원
|
|
129
228
|
act.GetDefault("CharShape", pset.HSet)
|
|
130
|
-
pset.TextColor =
|
|
131
|
-
pset.Bold =
|
|
132
|
-
pset.Italic =
|
|
133
|
-
pset.UnderlineType =
|
|
134
|
-
pset.Height =
|
|
135
|
-
pset.StrikeOutType =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
229
|
+
pset.TextColor = saved['TextColor']
|
|
230
|
+
pset.Bold = saved['Bold']
|
|
231
|
+
pset.Italic = saved['Italic']
|
|
232
|
+
pset.UnderlineType = saved['UnderlineType']
|
|
233
|
+
pset.Height = saved['Height']
|
|
234
|
+
pset.StrikeOutType = saved['StrikeOutType']
|
|
235
|
+
for attr in ['SpacingHangul', 'RatioHangul', 'SuperScript', 'SubScript',
|
|
236
|
+
'OutLineType', 'ShadowType', 'Emboss', 'Engrave', 'SmallCaps',
|
|
237
|
+
'UnderlineColor', 'StrikeOutColor']:
|
|
238
|
+
if saved.get(attr) is not None:
|
|
239
|
+
try:
|
|
240
|
+
setattr(pset, attr, saved[attr])
|
|
241
|
+
if attr == 'SpacingHangul':
|
|
242
|
+
pset.SpacingLatin = saved[attr]
|
|
243
|
+
if attr == 'RatioHangul':
|
|
244
|
+
pset.RatioLatin = saved[attr]
|
|
245
|
+
except Exception as e:
|
|
246
|
+
print(f"[WARN] Restore {attr}: {e}", file=sys.stderr)
|
|
148
247
|
act.Execute("CharShape", pset.HSet)
|
|
149
248
|
|
|
150
249
|
|
|
@@ -206,6 +305,71 @@ def set_paragraph_style(hwp, style=None):
|
|
|
206
305
|
pset.RightMargin = int(style["right_margin"] * 100)
|
|
207
306
|
except Exception as e:
|
|
208
307
|
print(f"[WARN] {e}", file=sys.stderr)
|
|
308
|
+
# 문단 앞 페이지 나누기
|
|
309
|
+
if "page_break_before" in style:
|
|
310
|
+
try:
|
|
311
|
+
pset.PagebreakBefore = 1 if style["page_break_before"] else 0
|
|
312
|
+
except Exception as e:
|
|
313
|
+
print(f"[WARN] PagebreakBefore: {e}", file=sys.stderr)
|
|
314
|
+
# 다음 문단과 함께
|
|
315
|
+
if "keep_with_next" in style:
|
|
316
|
+
try:
|
|
317
|
+
pset.KeepWithNext = 1 if style["keep_with_next"] else 0
|
|
318
|
+
except Exception as e:
|
|
319
|
+
print(f"[WARN] KeepWithNext: {e}", file=sys.stderr)
|
|
320
|
+
# 과부/고아 방지
|
|
321
|
+
if "widow_orphan" in style:
|
|
322
|
+
try:
|
|
323
|
+
pset.WidowOrphan = 1 if style["widow_orphan"] else 0
|
|
324
|
+
except Exception as e:
|
|
325
|
+
print(f"[WARN] WidowOrphan: {e}", file=sys.stderr)
|
|
326
|
+
# 줄 바꿈
|
|
327
|
+
if "line_wrap" in style:
|
|
328
|
+
try:
|
|
329
|
+
pset.LineWrap = int(style["line_wrap"])
|
|
330
|
+
except Exception as e:
|
|
331
|
+
print(f"[WARN] LineWrap: {e}", file=sys.stderr)
|
|
332
|
+
# 그리드에 맞춤
|
|
333
|
+
if "snap_to_grid" in style:
|
|
334
|
+
try:
|
|
335
|
+
pset.SnapToGrid = 1 if style["snap_to_grid"] else 0
|
|
336
|
+
except Exception as e:
|
|
337
|
+
print(f"[WARN] SnapToGrid: {e}", file=sys.stderr)
|
|
338
|
+
# 한영 자동 간격
|
|
339
|
+
if "auto_space_eAsian_eng" in style:
|
|
340
|
+
try:
|
|
341
|
+
pset.AutoSpaceEAsianEng = 1 if style["auto_space_eAsian_eng"] else 0
|
|
342
|
+
except Exception as e:
|
|
343
|
+
print(f"[WARN] AutoSpaceEAsianEng: {e}", file=sys.stderr)
|
|
344
|
+
if "auto_space_eAsian_num" in style:
|
|
345
|
+
try:
|
|
346
|
+
pset.AutoSpaceEAsianNum = 1 if style["auto_space_eAsian_num"] else 0
|
|
347
|
+
except Exception as e:
|
|
348
|
+
print(f"[WARN] AutoSpaceEAsianNum: {e}", file=sys.stderr)
|
|
349
|
+
# 영문 줄바꿈
|
|
350
|
+
if "break_latin_word" in style:
|
|
351
|
+
try:
|
|
352
|
+
pset.BreakLatinWord = int(style["break_latin_word"])
|
|
353
|
+
except Exception as e:
|
|
354
|
+
print(f"[WARN] BreakLatinWord: {e}", file=sys.stderr)
|
|
355
|
+
# 제목 수준
|
|
356
|
+
if "heading_type" in style:
|
|
357
|
+
try:
|
|
358
|
+
pset.HeadingType = int(style["heading_type"])
|
|
359
|
+
except Exception as e:
|
|
360
|
+
print(f"[WARN] HeadingType: {e}", file=sys.stderr)
|
|
361
|
+
# 줄 함께 유지
|
|
362
|
+
if "keep_lines_together" in style:
|
|
363
|
+
try:
|
|
364
|
+
pset.KeepLinesTogether = 1 if style["keep_lines_together"] else 0
|
|
365
|
+
except Exception as e:
|
|
366
|
+
print(f"[WARN] KeepLinesTogether: {e}", file=sys.stderr)
|
|
367
|
+
# 문단 압축
|
|
368
|
+
if "condense" in style:
|
|
369
|
+
try:
|
|
370
|
+
pset.Condense = int(style["condense"])
|
|
371
|
+
except Exception as e:
|
|
372
|
+
print(f"[WARN] Condense: {e}", file=sys.stderr)
|
|
209
373
|
|
|
210
374
|
act.Execute("ParaShape", pset.HSet)
|
|
211
375
|
|
|
@@ -463,8 +627,31 @@ def fill_table_cells_by_tab(hwp, table_idx, cells):
|
|
|
463
627
|
cell_style = cell.get("style")
|
|
464
628
|
if cell_style:
|
|
465
629
|
insert_text_with_style(hwp, text, cell_style)
|
|
630
|
+
# 셀 정렬은 텍스트 삽입 후 TableCellAlign 액션으로 적용
|
|
631
|
+
if "align" in cell_style:
|
|
632
|
+
align_action = {
|
|
633
|
+
"left": "TableCellAlignLeftCenter",
|
|
634
|
+
"center": "TableCellAlignCenterCenter",
|
|
635
|
+
"right": "TableCellAlignRightCenter",
|
|
636
|
+
"justify": "TableCellAlignLeftCenter",
|
|
637
|
+
}
|
|
638
|
+
action = align_action.get(cell_style["align"], "TableCellAlignLeftCenter")
|
|
639
|
+
hwp.HAction.Run(action)
|
|
466
640
|
else:
|
|
467
641
|
hwp.insert_text(text)
|
|
642
|
+
|
|
643
|
+
# 셀 수직 정렬/여백 설정 (HCell)
|
|
644
|
+
vert_align = cell.get("vert_align") # "top"|"middle"|"bottom"
|
|
645
|
+
if vert_align:
|
|
646
|
+
try:
|
|
647
|
+
va_map = {"top": 0, "middle": 1, "bottom": 2}
|
|
648
|
+
pset_cell = hwp.HParameterSet.HCell
|
|
649
|
+
hwp.HAction.GetDefault("CellShape", pset_cell.HSet)
|
|
650
|
+
pset_cell.VertAlign = va_map.get(vert_align, 0)
|
|
651
|
+
hwp.HAction.Execute("CellShape", pset_cell.HSet)
|
|
652
|
+
except Exception as e:
|
|
653
|
+
print(f"[WARN] VertAlign: {e}", file=sys.stderr)
|
|
654
|
+
|
|
468
655
|
result["filled"] += 1
|
|
469
656
|
|
|
470
657
|
except Exception as e:
|
|
@@ -573,8 +760,9 @@ def insert_markdown(hwp, md_text):
|
|
|
573
760
|
i += 1
|
|
574
761
|
continue
|
|
575
762
|
# 셀 파싱
|
|
576
|
-
|
|
577
|
-
|
|
763
|
+
# H3 fix: 빈 셀 유지 (앞뒤 빈 요소만 제거)
|
|
764
|
+
raw_cells = row_text.split('|')
|
|
765
|
+
cells = [c.strip() for c in raw_cells[1:-1]] # | 앞뒤 빈 요소 제거, 중간 빈 셀 유지
|
|
578
766
|
table_lines.append(cells)
|
|
579
767
|
i += 1
|
|
580
768
|
# 표 생성
|
|
@@ -907,12 +1095,8 @@ def set_cell_background_color(hwp, table_idx, cells):
|
|
|
907
1095
|
hwp.TableRightCell()
|
|
908
1096
|
current_tab = target_tab
|
|
909
1097
|
|
|
910
|
-
# 셀 배경색 설정 (
|
|
911
|
-
|
|
912
|
-
pset = hwp.HParameterSet.HCellShape
|
|
913
|
-
act.GetDefault("CellShape", pset.HSet)
|
|
914
|
-
pset.BackColor = hwp.RGBColor(r, g, b)
|
|
915
|
-
act.Execute("CellShape", pset.HSet)
|
|
1098
|
+
# 셀 배경색 설정 (pyhwpx 내장 cell_fill 사용)
|
|
1099
|
+
hwp.cell_fill((r, g, b))
|
|
916
1100
|
result["colored"] += 1
|
|
917
1101
|
|
|
918
1102
|
except Exception as e:
|
|
@@ -934,14 +1118,19 @@ def set_table_border_style(hwp, table_idx, cells=None, style=None):
|
|
|
934
1118
|
|
|
935
1119
|
table_idx: 표 인덱스
|
|
936
1120
|
cells: 특정 셀만 적용 시 [{"tab": int}, ...] (None이면 표 전체)
|
|
937
|
-
style: {
|
|
938
|
-
|
|
939
|
-
|
|
1121
|
+
style: {
|
|
1122
|
+
"line_type": int, # 0=없음, 1=실선, 2=파선, 3=점선, 4=1점쇄선, 5=2점쇄선
|
|
1123
|
+
"line_width": int, # pt 단위
|
|
1124
|
+
"color": "#RRGGBB", # 테두리 색상
|
|
1125
|
+
"edges": ["left","right","top","bottom"], # 적용할 방향 (생략 시 전체)
|
|
1126
|
+
}
|
|
940
1127
|
"""
|
|
941
1128
|
if style is None:
|
|
942
1129
|
style = {}
|
|
943
|
-
line_type = style.get("line_type", 1)
|
|
1130
|
+
line_type = style.get("line_type", 1)
|
|
944
1131
|
line_width = style.get("line_width", 0)
|
|
1132
|
+
border_color = style.get("color") # "#RRGGBB" 또는 None
|
|
1133
|
+
edges = style.get("edges", ["left", "right", "top", "bottom"]) # 기본: 전체
|
|
945
1134
|
|
|
946
1135
|
try:
|
|
947
1136
|
hwp.get_into_nth_table(table_idx)
|
|
@@ -958,13 +1147,21 @@ def set_table_border_style(hwp, table_idx, cells=None, style=None):
|
|
|
958
1147
|
act = hwp.HAction
|
|
959
1148
|
pset = hwp.HParameterSet.HCellBorderFill
|
|
960
1149
|
act.GetDefault("CellBorderFill", pset.HSet)
|
|
961
|
-
#
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1150
|
+
# 방향별 테두리 설정
|
|
1151
|
+
edge_map = {"left": "Left", "right": "Right", "top": "Top", "bottom": "Bottom"}
|
|
1152
|
+
for edge_name in edges:
|
|
1153
|
+
prop = edge_map.get(edge_name)
|
|
1154
|
+
if prop:
|
|
1155
|
+
setattr(pset, f"BorderType{prop}", line_type)
|
|
966
1156
|
if line_width:
|
|
967
|
-
|
|
1157
|
+
setattr(pset, f"BorderWidth{prop}", line_width)
|
|
1158
|
+
if border_color:
|
|
1159
|
+
try:
|
|
1160
|
+
r, g, b = _hex_to_rgb(border_color)
|
|
1161
|
+
color_attr = f"BorderColor{prop}" if prop != "Left" else "BorderCorlorLeft" # typo in COM
|
|
1162
|
+
setattr(pset, color_attr, hwp.RGBColor(r, g, b))
|
|
1163
|
+
except Exception as e:
|
|
1164
|
+
print(f"[WARN] BorderColor {prop}: {e}", file=sys.stderr)
|
|
968
1165
|
act.Execute("CellBorderFill", pset.HSet)
|
|
969
1166
|
modified += 1
|
|
970
1167
|
except Exception as e:
|
|
@@ -977,12 +1174,20 @@ def set_table_border_style(hwp, table_idx, cells=None, style=None):
|
|
|
977
1174
|
act = hwp.HAction
|
|
978
1175
|
pset = hwp.HParameterSet.HCellBorderFill
|
|
979
1176
|
act.GetDefault("CellBorderFill", pset.HSet)
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1177
|
+
edge_map = {"left": "Left", "right": "Right", "top": "Top", "bottom": "Bottom"}
|
|
1178
|
+
for edge_name in edges:
|
|
1179
|
+
prop = edge_map.get(edge_name)
|
|
1180
|
+
if prop:
|
|
1181
|
+
setattr(pset, f"BorderType{prop}", line_type)
|
|
984
1182
|
if line_width:
|
|
985
|
-
|
|
1183
|
+
setattr(pset, f"BorderWidth{prop}", line_width)
|
|
1184
|
+
if border_color:
|
|
1185
|
+
try:
|
|
1186
|
+
r, g, b = _hex_to_rgb(border_color)
|
|
1187
|
+
color_attr = f"BorderColor{prop}" if prop != "Left" else "BorderCorlorLeft"
|
|
1188
|
+
setattr(pset, color_attr, hwp.RGBColor(r, g, b))
|
|
1189
|
+
except Exception as e:
|
|
1190
|
+
print(f"[WARN] BorderColor {prop}: {e}", file=sys.stderr)
|
|
986
1191
|
act.Execute("CellBorderFill", pset.HSet)
|
|
987
1192
|
return {"status": "ok", "applied": "whole_table"}
|
|
988
1193
|
finally:
|