annyoung

python docx add border to image 본문

프로그래밍

python docx add border to image

nopsled 2024. 10. 14. 17:38

VBScript로 테두리 넣으려니 자꾸 에러가 난다.. 게다가 웹에서 보고서 뽑을때 Table 셀들을 Merge해서 다운로드하고 있는데, VBScript로 후처리를 해주는 것보다 보고서 생성하면서 테두리를 넣는게 좋지 않을까 싶어서 삽질을 좀 했다.

 

python docx-template 모듈을 사용중인데, 이미지 넣는것만 지원하고 border는 지원하지 않더라.

 

결국 docx xml 객체를 구현해야 하는데.. 우선 테두리가 없는 버전과 있는 버전의 xml을 비교했다.

 


  <pic:nvPicPr>
    <pic:cNvPr id="1745629617" name="그림 1745629617"/>
    <pic:cNvPicPr/>
  </pic:nvPicPr>
  <pic:blipFill>
    <a:blip r:embed="rId8"/>
    <a:stretch>
      <a:fillRect/>
    </a:stretch>
  </pic:blipFill>
  <pic:spPr>
    <a:xfrm>
      <a:off x="0" y="0"/>
      <a:ext cx="5731510" cy="3808095"/>
    </a:xfrm>
    <a:prstGeom prst="rect">
      <a:avLst/>
    </a:prstGeom>
  </pic:spPr>
</pic:pic>

이건 테두리 없는 이미지의 xml

 


  <pic:nvPicPr>
    <pic:cNvPr id="1745629617" name="그림 2" descr="텍스트, 소프트웨어, 스크린샷, 웹 페이지이(가) 표시된 사진&#10;&#10;자동 생성된 설명"/>
    <pic:cNvPicPr/>
  </pic:nvPicPr>
  <pic:blipFill>
    <a:blip r:embed="rId8"/>
    <a:stretch>
      <a:fillRect/>
    </a:stretch>
  </pic:blipFill>
  <pic:spPr>
    <a:xfrm>
      <a:off x="0" y="0"/>
      <a:ext cx="5731510" cy="3808095"/>
    </a:xfrm>
    <a:prstGeom prst="rect">
      <a:avLst/>
    </a:prstGeom>
    <a:ln>
      <a:solidFill>
        <a:schemeClr val="tx1"/>
      </a:solidFill>
    </a:ln>
  </pic:spPr>
</pic:pic>

이건 테두리가 있는 이미지인데.

 

<a:ln>
  <a:solidFill>
    <a:schemeClr val="tx1"/>
  </a:solidFill>
</a:ln>

자세히 보면 위 내용이 pic:spPr안에 들어간다.

 

def add_border_to_image(inline_shapes):
    for inline_shape in inline_shapes:
        schemeClr = OxmlElement('a:schemeClr')
        schemeClr.set('val', 'tx1')

        solidFill = OxmlElement('a:solidFill')
        solidFill.append(schemeClr)

        ln = OxmlElement('a:ln')
        ln.append(solidFill)
        inline_shape._inline.graphic.graphicData.pic.spPr.append(ln)
    return

나 같은 경우엔 워드 template에 포함된 모든 이미지에 테두리를 적용해야 했으므로 위와 같이 짰다. for loop 안에서 OxmlElement를 이용해 xml을 구성하지 않으면 안돌아가는데 왜 그런지 모르겠다.

 

add_border_to_image(doc.docx.inline_shapes)

테두리 넣는 함수 호출하고 doc.render()한 후에 doc.save()하면 된다.

 * 추가로 이미 테두리가 존재하는 이미지에 또 테두리를 넣게 되면 문서가 깨져서 열 수 없기 때문에, spPr안에 a:ln이나 a:schemeClr이 존재하는지 확인하는 루틴을 넣어야 한다.

Comments