Uses TSDocxEnumerations; Application := new TSDocxApplication(); path := SysparamStr(1); if path and LeftStr(path, 7) = "--path=" then begin path := path[8:] $ "\\OfficeVBA\\docx\\"; end savepath := "TSVbaDocxHelp.docx"; // document := Application.Documents.Open(FileName: openpath); document := Application.Documents.Add; document.Activate; ActiveDocument := Application.ActiveDocument; FirstPage(ActiveDocument); Preface(ActiveDocument); SupportedList(path, ActiveDocument); FAQ(ActiveDocument); AddTablesOfContents(ActiveDocument); ActiveDocument.SaveAs2(FileName : savepath); echo "ActiveDocument.SaveAs2 = " $ savepath $ "\n"; return; Function FirstPage(ActiveDocument); Begin para := ActiveDocument.Paragraphs.Last; para.Range.Text := "TSVBA"; para.Range.InsertBefore("天软"); para.Range.InsertAfter("帮助文档"); para.Range.Font.Bold := true; para.Range.Font.Size := 25; para.Range.Font.Apply(); para.Format.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); para.Format.Style := "Title"; para.Format.Apply(); // 写属性后要apply image := TOfficeTemplate('tinysoft.gif',true); shape := ActiveDocument.InlineShapes.AddPicture(image); shape.Width := 410; shape.Height := 75; shape.Apply(); ActiveDocument.Paragraphs.Add; ActiveDocument.Paragraphs(3).Range.InsertParagraphAfter(); ActiveDocument.Paragraphs(4).Range.InsertParagraphBefore(); range := ActiveDocument.Paragraphs(4).Range; range.Collapse(TSDocxEnumerations.wdCollapseEnd()); table := ActiveDocument.Tables.Add(Range:=range, NumRows:=3, NumColumns:=2, DefaultTableBehavior:=TSDocxEnumerations.wdWord9TableBehavior); println("ActiveDocument.Paragraphs.Count = {}", ActiveDocument.Paragraphs.Count); table.Columns(1).Width := 120; table.Columns(2).Width := 320; data := array(("文档名称", "TSVBA"), ("文档版本", "Version 1.0"), ("修订日期", Datetimetostr(now()))); for i:=1 to 3 do begin cell := table.Cell(i, 1); cell.Shading.Texture := TSDocxEnumerations.wdTexture27Pt5Percent; cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; cell.Shading.BackgroundPatternColor := TSDocxEnumerations.wdColorGray15; cell.Shading.Apply(); cell.Range.Text := data[i-1][0]; cell.Range.Font.Bold := true; cell.Range.Font.Apply(); cell := table.Cell(i, 2); cell.VerticalAlignment := TSDocxEnumerations.wdCellAlignVerticalCenter; cell.Range.Text := data[i-1][1]; cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); end ActiveDocument.Paragraphs.Add; para := ActiveDocument.Paragraphs.Last; para.Range.InsertBreak(TSDocxEnumerations.wdPageBreak()); End; Function AddTitle(ActiveDocument, text, level); Begin ActiveDocument.Paragraphs.Add; para := ActiveDocument.Paragraphs.Last; info := array( (22, TSDocxEnumerations.wdViolet(), TSDocxEnumerations.wdOutlineLevel1(), 0), (16, TSDocxEnumerations.wdDarkRed(), TSDocxEnumerations.wdOutlineLevel2(), 2), (16, TSDocxEnumerations.wdTeal(), TSDocxEnumerations.wdOutlineLevel3(), 15), ); index := level - 1; para.Range.Text := text; para.Range.Font.Size := info[index][0]; para.Range.Font.Bold := true; para.Range.Font.ColorIndex := info[index][1]; para.Range.Font.Apply(); para.Format.OutlineLevel := info[index][2]; para.Format.LeftIndent := info[index][3]; // para.Format.CharacterUnitLeftIndent := 0; para.Format.Apply(); para.Range.ListFormat.ApplyOutlineNumberDefault(); End; Function Preface(ActiveDocument); Begin AddTitle(ActiveDocument, "前言", 1); para := ActiveDocument.Paragraphs.Last; para.Format.PageBreakBefore := true; para.Format.Apply(); ActiveDocument.Paragraphs.Add; para := ActiveDocument.Paragraphs.Last; para.Range.Text := "该文档由docx_vba_help.tsl脚本自动生成。"; para.Range.Font.Size := 14; para.Range.Font.Italic := true; para.Range.Font.ColorIndex := TSDocxEnumerations.wdPink(); para.Range.Font.Apply(); para.Format.CharacterUnitFirstLineIndent := 2; para.Format.FirstLineIndent := 20; para.Format.Apply(); font := para.Range.Font.Duplicate; format := para.Format.Duplicate; ActiveDocument.Paragraphs.Add; para := ActiveDocument.Paragraphs.Last; para.Range.Text := "本项目基于TSOffice,使用前请先部署TSOffice。该项目以类VBA的方式,用TSL实现对excel、word的操作。"; para.Range.Font := font; para.Format := format; para.Range.Font.Italic := false; para.Range.Font.ColorIndex := TSDocxEnumerations.wdBlack(); para.Range.Font.Apply(); font := para.Range.Font.Duplicate; format := para.Format.Duplicate; ActiveDocument.Paragraphs.Add; para := ActiveDocument.Paragraphs.Last; para.Range.Text := "项目目前仅支持常用的操作,比如对段落、表格的操作。需注意该项目在使用时可能存在与VBA有差异的情况。具体支持列表如下:"; para.Range.Font := font; para.Format := format; End; Function SupportedList(path, ActiveDocument); Begin ActiveDocument.Paragraphs.Add; AddTitle(ActiveDocument, "TSVBA支持对象", 1); println("\n\nAuto generate classInfo.."); files := array( path + "TSDocxApplication.tsf", path + "border\\TSDocxBorder.tsf", path + "border\\TSDocxBorders.tsf", path + "TSDocxCell.tsf", path + "TSDocxCells.tsf", path + "TSDocxColumn.tsf", path + "TSDocxColumns.tsf", path + "TSDocxDocument.tsf", path + "TSDocxDocuments.tsf", path + "font\\TSDocxFont.tsf", path + "listformat\\TSDocxListFormat.tsf", path + "TSDocxInlineShape.tsf", path + "TSDocxInlineShapes.tsf", path + "TSDocxTable.tsf", path + "TSDocxTables.tsf", path + "TSDocxTablesOfContents.tsf", path + "paragraphformat\\TSDocxParagraphFormat.tsf", path + "TSDocxParagraphs.tsf", path + "TSDocxParagraph.tsf", path + "TSDocxRange.tsf", path + "TSDocxRows.tsf", path + "TSDocxRow.tsf", path + "shading\\TSDocxShading.tsf", ); // files := array( // path + "TSDocxTables.tsf", // ); for i:=0 to length(files)-1 do begin file := files[i]; name := ExtractFileName(file); name := name[7:length(name)-4]; AddTitle(ActiveDocument, name, 2); methods := array(); properties := array(); LoadClassInfo(file, methods, properties); AddMethods(ActiveDocument, methods); AddProperties(ActiveDocument, properties); println("file = {}, is OK!", file); end End; Function AddMethods(ActiveDocument, arr); Begin if not istable(arr) then return; methods := array(); for k, v in arr do if v = 2 then methods[k] := v; for k, v in arr do methods[k] := v; AddTitle(ActiveDocument, "方法支持情况", 3); para := ActiveDocument.Paragraphs.Last; row := length(methods) + 1; para.Range.Collapse(TSDocxEnumerations.wdCollapseEnd()); table := ActiveDocument.Tables.Add(Range := para.Range, NumRows := row, NumColumns := 2, DefaultTableBehavior := TSDocxEnumerations.wdWord9TableBehavior); table.Columns(1).Width := 220; table.Columns(2).Width := 220; init_title := function(cell, title); begin cell.Shading.Texture := TSDocxEnumerations.wdTexture12Pt5Percent; cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; cell.Shading.BackgroundPatternColorIndex := TSDocxEnumerations.wdTurquoise; cell.Shading.Apply(); cell.Range.Text := title; cell.Range.Font.Bold := true; cell.Range.Font.Size := 14; cell.Range.Font.ColorIndex := TSDocxEnumerations.wdRed(); cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); border := cell.Borders(TSDocxEnumerations.wdBorderBottom); border.LineStyle := TSDocxEnumerations.wdLineStyleTriple(); border.ColorIndex := TSDocxEnumerations.wdBlue(); border.Apply(); end ##init_title(table.Cell(1, 1), "VBA函数"); ##init_title(table.Cell(1, 2), "TSVBA是否支持"); i := 2; for k, v in methods do begin cell := table.Cell(i, 1); cell.Range.Text := k; cell.Range.Font.NameAscii := "Consolas"; cell.Range.Font.NameFarEast := "微软雅黑"; cell.Range.Font.Size := 11; cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); cell := table.Cell(i, 2); cell.Range.Text := v = 2 ? "✅" : "❌"; cell.Range.Font.NameAscii := "Segoe UI Emoji"; cell.Range.Font.NameOther := "Segoe UI Emoji"; cell.Range.Font.NameBi := "Segoe UI Emoji"; cell.Range.Font.Size := 11; cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); i++; end End; Function AddProperties(ActiveDocument, arr); Begin if not istable(arr) then return; properties := array(); for k, v in arr do if v["r"] = 2 or v["w"] = 2 then properties[k] := v; for k, v in arr do properties[k] := v; AddTitle(ActiveDocument, "属性支持情况", 3); row := length(properties) + 2; para := ActiveDocument.Paragraphs.Last; para.Range.Collapse(TSDocxEnumerations.wdCollapseEnd()); table := ActiveDocument.Tables.Add(Range := para.Range, NumRows := row, NumColumns := 4, DefaultTableBehavior := TSDocxEnumerations.wdWord9TableBehavior); table.Columns(1).Width := 110; table.Columns(2).Width := 110; table.Columns(3).Width := 110; table.Columns(4).Width := 110; table.Cell(1, 1).Merge(table.Cell(1, 2)); table.Cell(1, 3).Merge(table.Cell(1, 4)); init_title := function(cell, title); begin cell.Shading.Texture := TSDocxEnumerations.wdTexture22Pt5Percent; cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; cell.Shading.BackgroundPatternColor := TSDocxEnumerations.wdColorLime; cell.Shading.Apply(); cell.Range.Text := title; cell.Range.Font.Bold := true; cell.Range.Font.Size := 14; cell.Range.Font.ColorIndex := TSDocxEnumerations.wdRed(); cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); border := cell.Borders(TSDocxEnumerations.wdBorderBottom); border.LineStyle := TSDocxEnumerations.wdLineStyleTriple(); border.ColorIndex := TSDocxEnumerations.wdBlue(); border.Apply(); end ##init_title(table.Cell(1, 1), "VBA属性"); ##init_title(table.Cell(1, 3), "TSVBA是否支持"); init_info := function(cell, content); begin cell.Range.Text := content; cell.Range.Font.NameAscii := "Consolas"; cell.Range.Font.NameFarEast := "微软雅黑"; cell.Range.Font.Size := 12; cell.Range.Font.ColorIndex := TSDocxEnumerations.wdViolet(); cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); cell.Shading.Texture := TSDocxEnumerations.wdTexture7Pt5Percent; cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; cell.Shading.BackgroundPatternColor := TSDocxEnumerations.wdColorGray30; cell.Shading.Apply(); end ##init_info(table.Cell(2, 1), "属性名称"); ##init_info(table.Cell(2, 2), "读写"); ##init_info(table.Cell(2, 3), "读"); ##init_info(table.Cell(2, 4), "写"); i := 3; for k, v in properties do begin cell := table.Cell(i, 1); // println("k = {}", k); cell.Range.Text := k; cell.Range.Font.NameAscii := "Consolas"; cell.Range.Font.NameFarEast := "微软雅黑"; cell.Range.Font.Size := 11; cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); content := ""; if v["r"] then content += "读"; if v["w"] then content += "/写"; cell := table.Cell(i, 2); cell.Range.Text := content; cell.Range.Font.NameAscii := "Consolas"; cell.Range.Font.NameFarEast := "微软雅黑"; cell.Range.Font.Size := 11; cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); r := v["r"] = 2 ? "✅" : "❌"; cell := table.Cell(i, 3); cell.Range.Text := r; cell.Range.Font.NameAscii := "Segoe UI Emoji"; cell.Range.Font.NameOther := "Segoe UI Emoji"; cell.Range.Font.NameBi := "Segoe UI Emoji"; cell.Range.Font.Size := 11; cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); font := cell.Range.Font; w := v["w"] = 2 ? "✅" : "❌"; cell := table.Cell(i, 4); cell.Range.Text := w; cell.Range.Font.NameAscii := "Segoe UI Emoji"; cell.Range.Font.NameOther := "Segoe UI Emoji"; cell.Range.Font.NameBi := "Segoe UI Emoji"; cell.Range.Font.Size := 11; cell.Range.Font.Apply(); cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); cell.Range.ParagraphFormat.Apply(); i++; end End; Function FAQ(ActiveDocument); Begin ActiveDocument.Paragraphs.Add; AddTitle(ActiveDocument, "FAQ", 1); AddTitle(ActiveDocument, "TSVBA在使用上有哪些特别的地方", 2); FAQContent(ActiveDocument, "TSVBA重载了[]运算符,对于诸如Documents, Paragraphs, Tables, Borders等,均可用[]获取对应的对象"); FAQContent(ActiveDocument, "Documents := ActiveDocument.Documents; // 获取Documents对象"); FAQContent(ActiveDocument, "Document := Documents[2]; // 等价于 Documents.Item(2);"); AddTitle(ActiveDocument, "为什么设置了Font, Shading等时未生效", 2); FAQContent(ActiveDocument, "考虑到性能问题,类似xxx.Range.Font.Size := 10;并不会立即生效,需要手动调用Apply方法,如:"); FAQContent(ActiveDocument, "paragraph.Range.Font.Name := 'Consolas';"); FAQContent(ActiveDocument, "paragraph.Range.Font.Size := 12;"); FAQContent(ActiveDocument, "paragraph.Range.Font.Apply();"); FAQContent(ActiveDocument, "注意一:在应用Font, Shading, ParagraphFormat, border, ListFormat以及InlineShape时均需要执行Apply方法使得设置生效"); FAQContent(ActiveDocument, "注意二:使用这些类时,最多支持到两级赋值,比如说paragraph.Range.Font中,Range是第一级,paragraph是第二级。若使用paragraphs.Item(1).Range.Font,则不会生效。这里出现了第三级Paragraphs"); AddTitle(ActiveDocument, "如何使用VBA中的Enumerations", 2); FAQContent(ActiveDocument, "用了TSL的Unit特性,将用到的枚举项均封装到了TSDocxEnumerations中"); FAQContent(ActiveDocument, "Uses TSDocxEnumerations;"); FAQContent(ActiveDocument, "xxx := TSDocxEnumerations.WdBlack;"); AddTitle(ActiveDocument, "为什么目录无法计算页码", 2); FAQContent(ActiveDocument, "由于目录页码计算比较复杂,目前仅提供生成目录项功能,不支持页码的计算。"); FAQContent(ActiveDocument, "另外使用TablesOfContents.Add生成目录时,仅支持Range, UpperHeadingLevel, LowerHeadingLevel三个参数的设置,其余参数设置均无效。"); AddTitle(ActiveDocument, "为什么添加图片的FileName参数不生效", 2); FAQContent(ActiveDocument, "因为TSVBA中,FileName是一个二进制格式,需要传入的是图片的二进制内容,而不是路径"); End; Function FAQContent(ActiveDocument, text); Begin ActiveDocument.Paragraphs.Add; para := ActiveDocument.Paragraphs.Last; para.Range.Text := text; para.Range.Font.Name := "Consolas"; para.Range.Font.NameAscii := "Consolas"; para.Range.Font.NameFarEast := "微软雅黑"; para.Range.Font.Size := 12; para.Range.Font.Apply(); para.Format.CharacterUnitFirstLineIndent := 2; para.Format.FirstLineIndent := 20; para.Format.Apply(); End; Function AddTablesOfContents(ActiveDocument); Begin range := ActiveDocument.Paragraphs(16).Range; // println("range.text = {}", range.Text); range.Collapse(TSDocxEnumerations.wdCollapseStart()); ActiveDocument.TablesOfContents.Add(Range := range, UseHeadingStyles := true, UpperHeadingLevel := 1, LowerHeadingLevel := 9); End; Function LoadClassInfo(f, methods, properties); Begin [err,fh] := io_open(f); if err then return t; [err, data] := io_read(fh); io_close(fh); if err then return t; lines := str2array(string(data), "\n"); flag := true; for i:=0 to length(lines)-1 do begin line := lines[i]; if AnsiContainsText(line, "// Methods") then flag := false; if AnsiContainsText(line, "// Properties") then flag := true; if not flag and ParseRegExpr("\\s\+Function\\s\+(\\w+)\\(", line, "i", result, MPos, Mlen) and length(result) then methods[result[0][1]] := 1; if AnsiContainsText(line, "property") then begin ParseRegExpr("\\s\+property\\s\+(\\w+)\\s\+read\\s\+(\\w+)(\\s\+write\\s\+(\\w+))\?", line, "", result, MPos, Mlen); if not istable(result) then continue; rw := array(); if result[0][2] then rw["r"] := 1; if result[0][4] then rw["w"] := 1; properties[result[0][1]] := rw; end if AnsiContainsText(line, "End;") then break; end for j:=i to length(lines)-1 do begin line := lines[j]; if not AnsiContainsText(line, "Function") then continue; if ParseRegExpr("Function\\s\+.*\\.(\\w+)\\(", line, "i", result, MPos, Mlen) and istable(result) then begin name := result[0][1]; if not name then continue; if methods[name] then begin methods[name] := 2; continue; end if AnsiContainsText(name, "Read") then begin rname := name[5:]; if properties[rname] then properties[rname]["r"] := 2; end else if AnsiContainsText(name, "Write") then begin wname := name[6:]; if properties[wname] then properties[wname]["w"] := 2; end end end End; Function Test(); Begin line := "Function TSDocxTables.Add(Range, NumRows, NumColumns, DefaultTableBehavior, AutoFitBehavior);"; ParseRegExpr("Function\\s\+.*\\.(\\w+)\\(", line, "i", result, MPos, Mlen); println("result = {}", result); End;