两年没写体会了,这中间发生了很多有意义的事。包括顺利完成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二次开发,挣点零花钱。筒子们项目上有闲钱的恰好需要上述服务的,支援下,房租要涨价咯。