2013-07-25 26 views
19

Tôi đang tạo một số báo cáo odt/docx qua markdown bằng cách sử dụng knitr và pandoc và bây giờ tự hỏi làm thế nào bạn muốn đi về tạo bảng. Chủ yếu là tôi quan tâm đến việc thêm quy tắc (ít nhất là trên cùng, dưới cùng và một bên dưới tiêu đề, nhưng có thể thêm các quy tắc tùy ý bên trong bảng cũng sẽ tốt hơn).Thêm quy tắc tạo kiểu trong bảng pandoc cho đầu ra odt/docx (đường viền bảng)

Chạy ví dụ sau từ tài liệu hướng dẫn qua pandoc (không có bất kỳ tham số đặc biệt nào) chỉ cần tạo bảng "trơn" không có bất kỳ loại quy tắc/màu sắc/hướng dẫn nào (trong -t odt hoặc -t docx).

+---------------+---------------+--------------------+ 
| Fruit   | Price   | Advantages   | 
+===============+===============+====================+ 
| Bananas  | $1.34   | - built-in wrapper | 
|    |    | - bright color  | 
+---------------+---------------+--------------------+ 
| Oranges  | $2.10   | - cures scurvy  | 
|    |    | - tasty   | 
+---------------+---------------+--------------------+ 

Tôi đã nhìn qua "phong cách" cho khả năng xác định bảng Formating trong một tài liệu tham khảo .docx/.odt nhưng thấy không có gì rõ ràng hơn "tiêu đề bảng" và "nội dung bảng" phong cách, cả hai đều dường như chỉ quan tâm đến định dạng của văn bản trong bảng.

Khá quen thuộc với các trình xử lý tài liệu kiểu WYSIWYG, tôi bị mất làm cách tiếp tục.

Trả lời

20

Đây là cách tôi đã tìm kiếm làm thế nào để làm điều này:

Cách để thêm một bảng trong Docx là sử dụng thẻ <w:tbl>. Vì vậy, tôi đã tìm kiếm cho điều này trong kho github, và thấy nó in this file (gọi tắt là Nhà văn/Docx.hs, vì vậy nó không phải là một bất ngờ lớn)

blockToOpenXML opts (Table caption aligns widths headers rows) = do 
    let captionStr = stringify caption 
    caption' <- if null caption 
       then return [] 
       else withParaProp (pStyle "TableCaption") 
         $ blockToOpenXML opts (Para caption) 
    let alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)]() 
    let cellToOpenXML (al, cell) = withParaProp (alignmentFor al) 
            $ blocksToOpenXML opts cell 
    headers' <- mapM cellToOpenXML $ zip aligns headers 
    rows' <- mapM (\cells -> mapM cellToOpenXML $ zip aligns cells) 
      $ rows 
    let borderProps = mknode "w:tcPr" [] 
        [ mknode "w:tcBorders" [] 
         $ mknode "w:bottom" [("w:val","single")]() 
        , mknode "w:vAlign" [("w:val","bottom")]() ] 
    let mkcell border contents = mknode "w:tc" [] 
          $ [ borderProps | border ] ++ 
          if null contents 
           then [mknode "w:p" []()] 
           else contents 
    let mkrow border cells = mknode "w:tr" [] $ map (mkcell border) cells 
    let textwidth = 7920 -- 5.5 in in twips, 1/20 pt 
    let mkgridcol w = mknode "w:gridCol" 
         [("w:w", show $ (floor (textwidth * w) :: Integer))]() 
    return $ 
    [ mknode "w:tbl" [] 
     (mknode "w:tblPr" [] 
     ([ mknode "w:tblStyle" [("w:val","TableNormal")]() ] ++ 
      [ mknode "w:tblCaption" [("w:val", captionStr)]() 
      | not (null caption) ]) 
     : mknode "w:tblGrid" [] 
     (if all (==0) widths 
      then [] 
      else map mkgridcol widths) 
     : [ mkrow True headers' | not (all null headers) ] ++ 
     map (mkrow False) rows' 
    ) 
    ] ++ caption' 

Tôi không quen thuộc ở tất cả với Haskell, nhưng tôi có thể nhìn thấy rằng kiểu đường viền được mã hóa cứng vì không có biến nào trong đó:

let borderProps = mknode "w:tcPr" [] 
        [ mknode "w:tcBorders" [] 
         $ mknode "w:bottom" [("w:val","single")]() 
        , mknode "w:vAlign" [("w:val","bottom")]() ] 

Điều đó có nghĩa là gì?

Điều đó có nghĩa là bạn không thể thay đổi kiểu của bảng docx bằng phiên bản hiện tại của PanDoc. Howewer, có một cách để có được phong cách của riêng bạn.

Cách lấy phong cách của riêng bạn?

  1. Tạo một tài liệu Docx với phong cách mà bạn muốn trên bảng của bạn (bằng cách tạo ra bảng đó)
  2. Thay đổi phần mở rộng của tập tin đó và giải nén nó
  3. mở word/document.xml và tìm kiếm các <w:tbl>
  4. Hãy thử để tìm hiểu cách phong cách của bạn dịch sang XML và thay đổi borderProps theo những gì bạn thấy.

Dưới đây là một thử nghiệm với một border-style Tôi tạo ra: Custom border style

Và đây là XML tương ứng:

<w:tblBorders> 
    <w:top w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/> 
    <w:left w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/> 
    <w:bottom w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/> 
    <w:right w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/> 
    <w:insideH w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/> 
    <w:insideV w:val="dotted" w:sz="18" w:space="0" w:color="C0504D" w:themeColor="accent2"/> 
</w:tblBorders> 

gì về odt?

Tôi chưa xem xét, hãy hỏi xem bạn có không tự tìm thấy bằng phương pháp tương tự hay không.

Hope this helps và đừng ngần ngại hỏi một cái gì đó hơn

+0

Tôi sẽ chấp nhận điều này vì đây là lần đầu tiên. Tôi thậm chí không nghĩ đơn giản là kiểm tra mã (hoặc có lẽ tôi quá lười biếng và thích cho phép người khác làm điều đó;))! Cảm ơn! –

+0

Không phải lúc nào cũng dễ dàng kiểm tra mã khi bạn không quen với những gì đang xảy ra phía sau, ví dụ như cách tài liệu được cấu trúc, cách bảng được trình bày trong docx. Vì vậy, nó là bình thường. – edi9999

+1

Đây là một câu trả lời tuyệt vời. Tất cả các upvotes cho bạn @ edi9999. – Archonic

9

Cùng gợi ý như edi9999: hack nội dung xml của docx chuyển đổi.Và sau đây là mã R của tôi để làm điều đó.

Biến số tblPr chứa định nghĩa về kiểu được thêm vào các bảng trong docx. Bạn có thể sửa đổi chuỗi để đáp ứng nhu cầu của riêng bạn.

require(XML) 

docx.file <- "report.docx" 
tblPr <- '<w:tblPr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:tblStyle w:val="a8"/><w:tblW w:w="0" w:type="auto"/><w:tblBorders><w:top w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:left w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:bottom w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:right w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:insideH w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/><w:insideV w:val="single" w:sz="4" w:space="0" w:color="000000" w:themeColor="text1"/></w:tblBorders><w:jc w:val="center"/></w:tblPr>' 

## unzip the docx converted by Pandoc 
system(paste("unzip", docx.file, "-d temp_dir")) 
document.xml <- "temp_dir/word/document.xml" 

doc <- xmlParse(document.xml) 
tbl <- getNodeSet(xmlRoot(doc), "//w:tbl") 
tblPr.node <- lapply(1:length(tbl), function (i) 
        xmlRoot(xmlParse(tblPr))) 
added.Pr <- names(xmlChildren(tblPr.node[[1]])) 
for (i in 1:length(tbl)) { 
    tbl.node <- tbl[[i]] 
    if ('tblPr' %in% names(xmlChildren(tbl.node))) { 
     children.Pr <- xmlChildren(xmlChildren(tbl.node)$tblPr) 
     for (j in length(added.Pr):1) { 
      if (added.Pr[j] %in% names(children.Pr)) { 
       replaceNodes(children.Pr[[added.Pr[j]]], 
          xmlChildren(tblPr.node[[i]])[[added.Pr[j]]]) 
      } else { 
       ## first.child <- children.Pr[[1]] 
       addSibling(children.Pr[['tblStyle']], 
          xmlChildren(tblPr.node[[i]])[[added.Pr[j]]], 
          after=TRUE) 
      } 
     } 
    } else { 
     addSibling(xmlChildren(tbl.node)[[1]], tblPr.node[[i]], after=FALSE) 
    } 
} 

## save hacked xml back to docx 
saveXML(doc, document.xml, indent = F) 
setwd("temp_dir") 
system(paste("zip -r ../", docx.file, " *", sep="")) 
setwd("..") 
system("rm -fr temp_dir") 
4

edi9999 có câu trả lời tốt nhất nhưng đây là những gì tôi làm:

Khi tạo docx, sử dụng một docx tài liệu tham khảo để có được phong cách. Tham chiếu đó sẽ chứa một đống các kiểu khác mà Pandoc không dùng để tạo, nhưng chúng vẫn còn ở đó. Thông thường bạn sẽ nhận được các bộ mặc định, nhưng bạn cũng có thể thêm một kiểu bảng mới.

Sau đó, bạn chỉ cần cập nhật các file word \ document.xml để tham khảo các kiểu bảng mới, và bạn có thể làm điều đó theo chương trình (bằng cách giải nén, chạy sed, và cập nhật các kho lưu trữ docx), ví dụ:

7z.exe x mydoc.docx word\document.xml 
sed "s/<w:tblStyle w:val=\"TableNormal\"/<w:tblStyle w:val=\"NewTableStyle\"/g" word\document.xml > word\document2.xml 
copy word\document2.xml word\document.xml /y 
7z.exe u mydoc.docx word\document.xml 
+0

Câu trả lời này kết hợp với tùy chọn --reference-docx = là một kẻ giết người! – ivarec

2

thêm kiểu bảng có tên "TableNormal" trong reference.docx.

+0

Điều này không phù hợp với tôi khi Word (2010) phàn nàn về phong cách đó đang được bảo lưu. – mkingston

0

Chỉ cần thêm kiểu bảng mỗi thứ bạn muốn gọi là "Bảng" trong tệp tài liệu tham khảo。Và cập nhật pandoc thành mới nhất.

Các vấn đề liên quan