两年没写体会了,这中间发生了很多有意义的事。包括顺利完成Master Degree。走上攻城师的不归路。开始意识到压力之大,工资和房价的悬殊。唯有保持看书、思考,才能不让自己对现实的苦逼屈服,多学点东西,相信岩土工程还是很有钱途。 闲话少说,今天想谈谈工作中常需要做的一个事:出版。 无论是打印成pdf,还是发送到打印机,道理是类似的。 批量打印WORD,EXCEL,CAD的意义就不说了,大项目动辄几百张DWG汇总。 目前打印CAD有很多工具,很多人只是知道,但对于其原理还是不太清楚,一旦遇到故障了,也不知道如何解决。下面先讲讲批量打印的原理,贴一些代码,懂编程的同行可以拿回去稍加修改,做成自己想要的样子。 CAD有两个主要的表达空间,模型和布局,我们经常会在这两个空间类型里面打印图纸。 ‘================================================================= 模型modelspace的打印 通常是图框为一个外部参照(或某个特定图层上的多段线),批量打印的流程是: 打开dwg->配置打印参数->遍历modelspace里面的实体->找出参照对象->判断是否为图框对象->获取对象的范围(GetBoundingBox函数)->将范围赋值给打印设置->窗口方式打印->出图完成。 下面是这个流程的主要代码,逐句看看相信很快就能知道是怎么回事儿 ’============================================================== Dim ptMin As Variant, ptMaxAs Variant Dim Ent As AcadEntity Dim PlotCount As Integer Set objDoc = ThisDrawing.Application.ActiveDocument Set objLayout = objDoc.Layouts.Item("Model") Set objPlot = objDoc.Plot ThisDrawing.Application.ZoomExtents ' 设置打印机 If Not Trim(PrinterName) ="" Then objLayout.ConfigName ="pdfFactory Pro" Else Exit Sub End If ' 设置打印样式表 objLayout.StyleSheet = "acad.ctb" objLayout.CanonicalMediaName = "A3" ' 设置图纸单位 objLayout.PaperUnits = acMillimeters ' 设置默认图纸打印方向 objLayout.PlotRotation= ac0degrees '横向 ' 设置图纸打印比例 objLayout.StandardScale = ac1_1 objLayout.UseStandardScale = True '使用标准打印比例 ' 设置图纸是否居中打印 objLayout.CenterPlot = True ' 打印时使用图形文件中的线宽 objLayout.PlotWithLineweights = True ' 设置是否应用打印样式 objLayout.PlotWithPlotStyles = True ' 将打印错误报告切换为静默错误模式,以便不间断地执行打印任务 objPlot.QuietErrorMode = True ' 重新生成当前图形 objDoc.Regen acAllViewports ' 设置前台打印,使打印任务按打印顺序依次发送到打印机 objDoc.SetVariable "BACKGROUNDPLOT",0 '至此配置打印机完成。准备查找图框 For Each Ent In objDoc.ModelSpace If TypeOf Ent IsAcadBlockReference Then ‘如果对象是参照的话,进入下面判断 IfIsFrame(Ent, AutoFrame) = True And objDoc.Blocks(Ent.Name).count > 0 Then Ent.GetBoundingBox ptMin, ptMax Debug.Print Ent.Name & "--"& objDoc.Blocks(Ent.Name).count ' 将三维点转化为二维点坐标 ReDim Preserve ptMin(0 To1) ReDim Preserve ptMax(0 To1) ' 设置打印窗口 ThisDrawing.ActiveLayout.SetWindowToPlotptMin, ptMax objLayout.PlotType = acWindow End If objPlot.PlotToDevice objLayout.ConfigName '这句话就是发送到打印机了、 End If Next Ent ‘其中IsFrame函数为 Public FunctionIsFrame(entobj As Object, AutoMode As Boolean) As Boolean '判断是否为图框 On Error Resume Next IsFrame = False Dim i As Integer Dim FrmNameList As Variant FrmNameList = "blkFrame,A1,A2,A3,TK,图框" '图框块、编组名列表 FrmNameList = Split(FrmNameList, ",") For i = 0 To UBound(FrmNameList) If entobj.Name = FrmNameList(i) Then IsFrame = True Exit For End If Next End Function ’========================================================= 当图框不是参照,是位于某个图层上的多段线时,我们可以通过构建选择集,将那个图层上的多段线加入,然后遍历选择集(同橙色部分)dim ent as acadpolyline或acadlightpolyline,然后还是getboundingbox获取打印范围。 布局layout的打印 其批量打印的原理可以不同,这取决于制图习惯。对于自动成图的比如桥和路线,通常是一个布局一张图,一个cad几十个布局序列。还有一种是一个布局里面很多张图,每个图有一个图框参照。 对于前一种情况,方法为 遍历dwg的layouts集合,对一个集合layout(i)进行如上的配置,注意 objLayout.CenterPlot = false,布局不能居中打印。 dim i as acadlayout for each i in acadoc.layouts '将上面的代码中 objLayout换成i,配置打印机,打印方式PlotType = acLayout,此处省略重复。 i.PlotToDevice i.ConfigName next 如此,即可把所有布局打印。 对于一个布局里面很多个图纸的,同上,例如layout(i)里面很多,那就遍历layout(i)里面的外部参照,将每个参照的GetBoundingBox获取下来,采用plotType=acWindow的方式,同modelspace一样的方法打印 如果仔细看到这里,有一定的VBA基础的同行们,估计已经知道CAD内部的打印原理了,过去一直没静下研究下这个,最近花了点时间看明白后,就自己写了一个,然后集成了自动打印word和excel。现在遇到不工作,或者打印图纸方向不对,纸张不对的,就可以随时对源代码修改。 关于打印WORD和excel,大家可以用录制宏的办法,查看自动生成的代码,然后修改移植,就可以放到VB6.0或者VB.NET里面了。 用VB.net或6.0采用com组件独立编制exe程序时,区别是程序启动时定义AcadApp=GetObject(,"AutoCAD.Application) 或new一个Application。Thisdrawing替换为AcadDoc=AcadApp.ActiveDocument. 今天先到这,敲累了休息下,U盘没带回来。 另外国庆七天假,祝各位同行朋友玩的愉快。 最后插一句广告,承接边坡支护设计(计算书,施工图,数量表),搞地基处理设计图,搞小型基坑支护。也搞CAD,excel二次开发,挣点零花钱。筒子们项目上有闲钱的恰好需要上述服务的,支援下,房租要涨价咯。 ![]() |
|