生成DocX表格的方法

编程应用中经常要报表。
本文摘自vs2015、netframework4.61、vb.net源代码,代码本身均不依赖于word环境。

方法一:使用DocX

我需要生成这样的表,下图是mb_MC.docx:

''''安装并引用包,.Net FrameWork 4.0 ,Docx.dll
''install-package docx -version 1.3.0 
Imports Xceed.Words.NETSub do_Docx()Dim dx As DocX = DocX.Load("mb_MC.docx")Dim t = dx.Tables(0)Dim r0 = t.Rows(1)'备份第二行,含格式Dim nr =8, nc =6Dim ir, ic As IntegerFor ir = 0 To nrDim r1 As Row = t.InsertRow(r0, ir + 2) '相当于复制第二行,后面均对新行处理For ic = 0 To nc - 1 '填文本Dim tx ="字段值" '数据来源DataTable的行,...Dim p0 = r1.Cells(ic).Paragraphs(0).Append(tx) '如果格内有其它内容,可以改为替换'p0的格式设置...NextDim p = r1.Cells(nc).Paragraphs(0) '最后列添加图片Dim f1 = "you关联图片.jpg"If File.Exists(f1) ThenDim img As Image = dx.AddImage(f1)Dim pic = p.AppendPicture(img.CreatePicture(44, 33)) '填图片,设置高、宽Elsep.Append("没照片")End If	    Nextt.RemoveRow(1)dx.SaveAs("f.docx")
End Sub

感谢作者:https://github.com/xceedsoftware/docx

方法二:使用TemplateEngine.Docx

模板的创建mb_MC_T.docx(用到了内容控件和图片控件,需要重复的行由内容控件T1包裹):

'Install-Package TemplateEngine.Docx -Version 1.1.4   '.net46+
Imports TemplateEngine.DocxSub do_DocxT(dt as DataTable,fDx as Sring)File.Copy("mb_MC_T.docx", fDx, True)   '要Try	Dim TC = New TableContent("T1")		'创建表行重复For Each dr As DataRow In dt.RowsDim ar1 = New List(Of IContentItem)() '文档一行,含FieldContent和ImageContent''内容字段For Each c as DataColumn in dt.Columnsdim k = c.ColumnNamedim v = dr(k).ToString() ar1.Add(new FieldContent(k, v))Next''添加照片,在模板中为 图片控件Dim f1 = "you关联图片.jpg"Dim bb As Byte()=If(File.Exists(f1),File.ReadAllBytes(f1),New Byte() {}) '读wu.jpgar1.Add(New ImageContent("pic", bb))''一行TC.AddRow(ar1.ToArray())NextDim fillData = New Content(TC, New FieldContent("other", "其它内容值"))	Using TP As TemplateProcessor = New TemplateProcessor(fDx)TP.SetRemoveContentControls(True).SetNoticeAboutErrors(False)'debug时:TrueTP.FillContent(fillData)'在此,还有啥要处理:TP.Document.Descendants ... ...TP.SaveChanges()End UsingProcess.Start(fDx) 'try
End Sub

有Content、TableContent、FieldContent、ImageContent、RepeatContent、ListContent等等
感谢作者:https://github.com/UNIT6-open/TemplateEngine.Docx

方法三:直接生成rtf吧

用编辑软件做模板,另存为rtf,经写字板(wordpad.exe)打开、保存,精简一下,内容行就是这样子的:

xxx\cell xxx\cell xxx\cell xxx\cell xxx\cell xxx\cell <图片串>\cell\row
Private Sub do_Rtf(rr As DataRow(), f0 As String)Dim sw As StreamWriterTrysw = New StreamWriter(f0, False, System.Text.Encoding.Default)  '不追加Catch e As ExceptionMsgBox(e.Message, MsgBoxStyle.Critical)Exit SubEnd TryDim rtfH = "{\rtf1\ansi {\fonttbl{\f15\fnil 宋体}{\f16\fnil 黑体}}
{\colortbl;\red0\green0\blue255;\red0\green255\blue0;\red255\green255\blue0;\red255\green0\blue0;\red0\green0\blue0;}
\paperw16840\paperh11907\margl880\margr880\margt880\margb567\gutter0 \lndscpsxn\viewkind1\viewscale100\headery600\footery567
{\header \brdrb\brdrs\brdrw5 \fs18\cf5\qj <HHH> \par}
{\footer \fs18\cf5\qr {\field{\*\fldinst {PAGE}}} / {\field{\*\fldinst {NUMPAGES}}} 页 \par }".Replace("<HHH>", f0)sw.WriteLine(rtfH)'列头、列宽,对应Dim cc = {"学号", "姓名", "性别", "", "", "",  "照片"}Dim cw As Single() = {2.7, 1.7, 1, 2.0, 2.0, 2.0, 1.5} 'cmsw.WriteLine("\fs18\trowd\trqc\trleft-108\trrh400")'表格定义Dim ww As Integer = 0For i As Integer = 0 To cw.Length - 1ww += cw(i) * 567sw.WriteLine("\clvertalc\clbrdrt\brdrs\clbrdrl\brdrs\clbrdrb\brdrs\clbrdrr\brdrs\cltxlrtb \cellx" & ww)Nextsw.Write("\pard \intbl{")'开始 intbl'表头行sw.Write("\qc \fs21 {\b\qc ")sw.Write(String.Join("\cell ", cc))sw.WriteLine("\cell\row}")'表格内容行,循环sw.Write(\trrh567")  '行高1CMFor Each r As DataRow In rr'文本列''sw.Write("\qc ")        For ic = 0 To cc.Length - 2sw.Write(r(cc(ic)).ToString() & "\cell ")Next'照片Dim ff = "you关联照片.jpg"Dim zp = If(File.Exists(ff), rtf_PicStr(ff, 495), "无照片")sw.WriteLine($"\qc {zp}\cell\row")Nextsw.WriteLine("}\pard") ''end intbl    sw.WriteLine("}")	''end rtfsw.Flush()sw.Close()
End Sub

链接图片文件名就简单了。内嵌的rtf图片串难搞?

Private Function rtf_picStr(fjpg As String, w缇 As Integer) As String'1 twips缇的长度等于1/1440英寸;1/567厘米;1/20磅;1英寸=2.54厘米If not File.Exists(fjpg) Then Return ""Dim s = ""Dim m = New System.IO.MemoryStream()TryDim bp = New System.Drawing.Bitmap(fjpg)bp.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg)Dim h缇 As Integer = w缇 * bp.Height / bp.Width '保持长宽比Dim s1 = $"\pict\jpegblip\picwgoal{w缇}\pichgoal{h缇}\hex "	Dim s2 As String =BitConverter.ToString(m.GetBuffer(), 0).Replace("-", String.Empty)bp.Dispose()s = "{\*\shppict{" & s1 & s2 & "}}"Catchs = "无"Finallym.Close()m.Dispose()End TryReturn s
End Function

如果你有空闲时间优化rtf模板,这是运行最快的方法了。

更多的方法:
直接生成xml,类似于rtf;
还可以用openxml SDK生成代码…
值得参考java下poi-tl:http://deepoove.com/poi-tl/

End,vs2015,NetFramework4.61测试通过。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部