Delphi + Word solution reference. These are several functions I made during the project. I saw that everyone is asking questions about Word. Now take it out and share it with everyone. (I hope some friends can further add new functions, or make them into packages or libs, etc., to make it more convenient for everyone to use. I don’t have time myself, haha) Before use, create an empty WORD file as a template according to your needs. In the template Various formats and text are set in the file. In addition, the parameter of PRnWordTable is a TDBGridEh type control, which is taken from Ehlib2.6. The shFileCopy function (used to copy files) and the guiInfo function (used to display a message box) are also written by myself, and the codes are also attached. The sample code is as follows: Functions of code completion: 1. Replace the "#TITLE#" text in the printing template with "Demo Code 1" 2. And insert the content currently displayed by the DBGridEh1 control to the end of the document 3. Insert a blank line at the end of the document 4. Insert a new line of text at the end of the document 5. Remove the blank lines in the document if PrnWordBegin('C:/Print template.DOC','C:/Target file 1.DOC') then begin PrnWordReplace('#TITLE#','Demo code 1'); PrnWordTable(DBGridEh1); PrnWordInsert(''); PrnWordInsert('This is a new line of text'); PrnWordReplace('^p^p','^p ',true); PrnWordSave; end; The source code is as follows: //Word printing (declaration part) wDoc,wApp:Variant; function PrnWordBegin(tempDoc,docName:String):boolean; function PrnWordReplace(docText,newText:String;bSimpleReplace:boolean=false):boolean; function PrnWordInsert(lineText:String;bNewLine:boolean=true): boolean;overload; function PrnWordInsert(var imgInsert:TImage;sBookMark:String=''):boolean;overload; function PrnWordInsert(var chartInsert:TChart;sBookMark:String=''):boolean;overload; function PrnWordTable(var dbG:TDBGridEh;sBookMark:String='' ):boolean; procedure PrnWordSave; procedure PrnWordEnd; //Word printing (implementation part) { Function: Create a new target file docName based on the template file tempDoc and open the file } function PrnWordBegin(tempDoc,docName:String):boolean;begin result:=false; //Copy template if tempDoc<>'' then if not shFileCopy(tempDoc, docName) then exit; //Connect to Word try wApp:=CreateOleObject('Word.application'); except guiInfo('Please install Microsoft Word first.'); exit; end; try //Open if tempDoc='' then begin //Create a new document wDoc:=wApp.Document.Add; wDoc.SaveAs(docName); end else begin //Open the template wDoc:=wApp.Documents. Open(docName); end; except guiInfo('Failed to open the template, please check whether the template is correct. '); wApp.Quit; exit; end; wApp.Visible:=true; result:=true;end; { Function: Use newText to replace docText content bSimpleReplace : When true, only simple replacement is performed, when false, the new text is wrapped. Processing } function PrnWordReplace(docText,newText:String;bSimpleReplace:boolean=false):boolean;var i:Integer;begin if bSimpleReplace then begin //Simple processing, directly perform the replacement operation try wApp.Selection.Find.ClearFormatting; wApp.Selection.Find.Replacement.ClearFormatting; wApp.Selection.Find.Text := docText; wApp.Selection.Find.Replacement.Text :=newText; wApp.Selection.Find.Forward := True; wApp.Selection.Find.Wrap := wdFindContinue; wApp.Selection.Find.Format := False; wApp.Selection.Find.MatchCase := False; wApp.Selection.Find.MatchWholeWord := true; wApp.Selection.Find.MatchByte := True; wApp.Selection. Find.MatchWildcards := False; wApp.Selection.Find.MatchSoundsLike := False; wApp.Selection.Find.MatchAllWordForms := False; wApp.Selection.Find.Execute(Replace:=wdReplaceAll); result:=true; except result:=false; end; exit; end; //Automatically branch into lines reWord.Lines. Clear; reWord.Lines.Add(newText); try //Locate behind the position to be replaced wApp.Selection.Find.ClearFormatting; wApp.Selection.Find.Text := docText; wApp.Selection.Find.Replacement.Text := ''; wApp.Selection.Find.Forward := True; wApp.Selection.Find.Wrap := wdFindContinue; wApp.Selection .Find.Format := False; wApp.Selection.Find.MatchCase := False; wApp.Selection.Find.MatchWholeWord := False; wApp.Selection.Find.MatchByte := True; wApp.Selection.Find.MatchWildcards := False; wApp.Selection.Find.MatchSoundsLike := False; wApp.Selection.Find. MatchAllWordForms := False; wApp.Selection.Find.Execute; wApp.Selection.MoveRight(wdCharacter,1); //Start inserting line by line for i:=0 to reWord.Lines.Count-1 Do begin //Insert the current line wApp.Selection.InsertAfter(reWord.Lines[i]) ; //Except for the last line, automatically add new lines if i<reWord.Lines.Count-1 then wApp.Selection.InsertAfter(#13); end; //Delete the replacement mark wApp.Selection.Find.ClearFormatting; wApp.Selection.Find.Replacement.ClearFormatting; wApp.Selection.Find.Text := docText; wApp.Selection.Find.Replacement.Text := ''; wApp .Selection.Find.Forward := True; wApp.Selection.Find.Wrap := wdFindContinue; wApp.Selection.Find.Format := False; wApp.Selection.Find.MatchCase := False; wApp.Selection.Find.MatchWholeWord := true; wApp.Selection.Find.MatchByte := True; wApp.Selection.Find. MatchWildcards := False; wApp.Selection.Find.MatchSoundsLike := False; wApp.Selection.Find.MatchAllWordForms := False; wApp.Selection.Find.Execute(Replace:=wdReplaceAll); result:=true; except result:=false; end;end; { Function: Print the content currently displayed by TDBGridEh. Based on the format and content of the TDBGridEh control, a Word table is automatically generated at the sBookMark bookmark in the document. Currently, it can support cell alignment, multi-line titles (two lines), bottom totals and other features. sBookMark : Word The name of the bookmark to be inserted into the table } function PrnWordTable(var dbG:TDBGridEh;sBookMark:String=''):boolean;var iCol,iLine,i,j,k:Integer; wTable,wRange:Variant; iRangeEnd:longint; iGridLine,iTitleLine:Integer; getTextText:String;getTextDisplay:boolean; titleList:TStringList;titleSplit,titleCol:Integer;lastTitleSplit,SubTitle: Integer;lastTitle:String;begin result:=false; try //Calculate the number of columns in the table (excluding hidden columns) iTitleLine:=1; //Always default to 1 iCol:=0; for i:=0 to dbG.Columns.Count-1 Do begin if dbG.Columns[i].Visible then begin iCol:=iCol+1; end; end; //Calculate the number of rows in the table (excluding hidden columns) if dbG.DataSource.DataSet.Active then iLine:=dbG.DataSource.DataSet.RecordCount else iLine:=0; iGridLine:=iLine+iTitleLine+dbG.FooterRowCount; //Position the insertion point if sBookMark='' then begin //In At the end of the document iRangeEnd:=wDoc.Range.End-1; if iRangeEnd<0 then iRangeEnd:=0; wRange:=wDoc.Range(iRangeEnd,iRangeEnd); end else begin //At the bookmark wRange:=wDoc.Range.Goto(wdGoToBookmark,,,sBookMark); end; wTable:=wDoc.Tables. Add(wRange,iGridLine,iCol); wTable.Columns.AutoFit; //Title row k:=1; for j:=1 to dbG.Columns.Count Do begin if dbG.Columns[j-1].Visible then begin if dbG.UseMultiTitle then begin titleList:=strSplit(dbG.Columns[j-1].Title.Caption,' |'); wTable.Cell(1,k).Range.InsertAfter(titleList.Strings[0]); end else wTable.Cell(1,k).Range.InsertAfter(dbG.Columns[j-1].Title.Caption); //Set cell alignment if dbG.Columns[j-1].Title.Alignment=taCenter then wTable.Cell(1,k).Range.ParagraphFormat.Alignment:=wdAlignParagraphCenter else if dbG.Columns[j-1].Title.Alignment=taRightJustify then wTable.Cell(1,k).Range.ParagraphFormat.Alignment:=wdAlignParagraphRight else if dbG.Columns[j-1].Title.Alignment=taLeftJustify then wTable.Cell(1,k).Range.ParagraphFormat.Alignment:=wdAlignParagraphJustify; k:=k+1; end; end; //Fill in each row if iLine>0 then begin dbG.DataSource.dataset.DisableControls; dbG. DataSource.DataSet.First; for i:=1 to iLine Do begin k:=1; for j:=1 to dbG.Columns.Count Do begin if dbG.Columns[j-1].Visible then begin if dbG.Columns[j-1].FieldName<>'' then //Avoid errors due to empty columns begin //If the column If you have your own formatting display function, call the display function to get the display string getTextText:=''; if Assigned(dbG.DataSource.DataSet.FieldByName(dbG.Columns[j-1].FieldName).OnGetText) then begin dbG.DataSource.DataSet.FieldByName(dbG.Columns[j-1].FieldName).OnGetText(dbG.DataSource.DataSet.FieldByName(dbG.Columns[j-1].FieldName),getTextText,getTextDisplay); wTable.Cell(i+iTitleLine,k).Range.InsertAfter(getTextText); end else begin //Use database content to display wTable.Cell(i+iTitleLine,k).Range.InsertAfter(dbG.DataSource.DataSet.FieldByName( dbG.Columns[j-1].FieldName).AsString); end; end;