Skip to content

Instantly share code, notes, and snippets.

@freb

freb/addrefs.go

Created Feb 27, 2019
Embed
What would you like to do?
package main
import (
"fmt"
"log"
"os"
"regexp"
"strings"
"baliance.com/gooxml"
"baliance.com/gooxml/schema/soo/ofc/sharedTypes"
"baliance.com/gooxml/schema/soo/wml"
"baliance.com/gooxml/document"
)
var (
TableIdxReq1 = 40
TableIdxReq2 = 41
TableIdxReq3 = 42
TableIdxReq4 = 43
TableIdxReq5 = 44
TableIdxReq6 = 45
TableIdxReq7 = 46
TableIdxReq8 = 47
TableIdxReq9 = 48
TableIdxReq10 = 49
TableIdxReq11 = 50
TableIdxReq12 = 51
TestProcNoRegexp = regexp.MustCompile(`^\s*(\d+(\.\d+)+(\.[a-z]){0,1})\s`)
ReportTxtHolder = "<Report Findings Here>"
ReportTxtPrefix = "ref-"
)
func main() {
// gooxml.DisableLogging()
if len(os.Args) < 1 {
fmt.Println("first argument must be document name")
os.Exit(1)
}
doc, err := document.Open(os.Args[1])
if err != nil {
log.Fatalf("error opening document: %v\n", err)
}
// fmt.Println(len(doc.Tables()))
// fmt.Println(doc.X().Body)
// Add report text refs
for i := TableIdxReq1; i <= TableIdxReq12; i++ {
AddReportTextRefs(doc, i)
}
doc.SaveToFile(os.Args[2])
}
// AddReportTextRefs iterates the table at index tableIdx and adds the
// correct report text refs. The doc should contain text matching ReportTxtHolder
// in all cells requiring report text, otherwise the numbering will be off. Caller
// is responsible for setting SetUpdateFieldsOnOpen(true) on doc.Settings and
// saving the result.
func AddReportTextRefs(doc *document.Document, tableIdx int) {
tpNo := ""
rtIdx := 1
for _, row := range doc.Tables()[tableIdx].Rows() {
if tpn := TestProcNo(row); tpn != "" {
tpNo = tpn
rtIdx = 1
}
for _, cell := range row.Cells() {
for _, para := range cell.Paragraphs() {
for _, run := range para.Runs() {
fieldDefault := FindFldCharText(run, ReportTxtHolder)
if fieldDefault == nil {
// fmt.Println("fldChar not matching placeholder. Paragraph=", mergeRuns(para.Runs()))
// possibly check if run has a FldChar, but wasn't matched
continue
}
rtVal := fmt.Sprintf("%s%s-%d", ReportTxtPrefix, tpNo, rtIdx)
fieldDefault.ValAttr = rtVal
fmt.Println(rtVal)
rtIdx++
// replace fieldDefualt string with my string
}
}
// txt := mergeParas(cell.Paragraphs())
// if txt == "<Report Findings Here>" {
// fmt.Printf("%v-%v (%v)\n", tpNo, rtIdx, len(cell.Paragraphs()))
// rtIdx++
// // there may be some with an extra return, making more than one paragraph
// }
}
}
}
// take a row, return the report text cell and the test proc no.
func TestProcNo(run document.Row) string {
if len(run.Cells()) < 2 {
return ""
}
paraTxt := mergeParas(run.Cells()[0].Paragraphs())
matchGroups := TestProcNoRegexp.FindStringSubmatch(paraTxt)
if len(matchGroups) >= 2 {
return matchGroups[1]
}
return ""
}
// FindFldCharText searches all content elements in a run for a FldChar
// with default text matching s. The string pointer is returned so that the
// text can be manipulated by the caller.
// NOTE: i'm not even currently matching the string...
func FindFldCharText(run document.Run, s string) *wml.CT_String {
for _, ic := range run.X().EG_RunInnerContent {
if ic.FldChar != nil && ic.FldChar.FfData != nil && ic.FldChar.FfData.TextInput != nil && ic.FldChar.FfData.TextInput.Default != nil {
// mark them dirty here for now, but really should be done elsewhere:
ic.FldChar.DirtyAttr = &sharedTypes.ST_OnOff{}
ic.FldChar.DirtyAttr.Bool = gooxml.Bool(true)
// there is some caching of field text being displayed. try setting SetUpdateFieldsOnOpen
// ic.FldChar.FfData.CalcOnExit[0].ValAttr = &sharedTypes.ST_OnOff{Bool: &[]bool{true}[0]}
return ic.FldChar.FfData.TextInput.Default
}
}
return nil
}
func mergeRuns(runs []document.Run) string {
s := "" // use string builder or bytes.buffer using buf.WriteString and returning buf.String()
for _, run := range runs {
s += run.Text()
}
return s
}
func mergeParas(paras []document.Paragraph) string {
s := ""
for _, para := range paras {
s += mergeRuns(para.Runs())
}
return s
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment