AutoCAD VBA 橫斷面繪製自動化(疏濬用)
新版本請參考 VBA @ 一般渠道疏濬圖
前言:
2. 點選 "斷面填寫" 後依照指示填寫。(會先偵測前次的最後樁號,填入樁號需比它後面)
P.S2:結束點代表為板橋或箱涵的上斷面,在土石方計算表中會多安插一列空白行隔開。
前言:
因應筆者所在的灌溉給水區域為濁水系統,外加上坡度比較緩和,常需要有疏濬的工作要執行,每次在計算疏濬土方量的時候,畫一下縱橫斷面也是不可避免的。現地的狀況由該擔當區的人員最能理解土方分布情況,但又受限於繪製CAD斷面也是一門學問,因而引發我寫了一個side project將原本在CAD中設定斷面高程的部分以Excel表的形式代替,爾後再由CAD中的dvb檔去連結設定檔,達到參數化製圖的目的。
使用方法:
1. 設定該灌溉系統的起訖點、渠道形式(U型溝、內面工)及尺寸(Unit:M)。
圖一、排序必須由上到下遞增,不能有空白。 |
2. 點選 "斷面填寫" 後依照指示填寫。(會先偵測前次的最後樁號,填入樁號需比它後面)
圖二、Buttom位於工作表1:橫斷面繪製資料。 |
P.S:如左側有剩餘資料,請先點選 "刪除資料"。
3. 填寫時若是板橋、箱涵等較難疏濬的地方,請在樁號填寫上or下,代表上斷面or下斷面
4. 填寫左右環境參數後、各點高程以及是否為結束點(END?),如已知下一個的樁號可填寫 下 一個間距,點按OK後不會再進行詢問。
圖三、Excel VBA中的userform。 |
P.S2:結束點代表為板橋或箱涵的上斷面,在土石方計算表中會多安插一列空白行隔開。
5.如果要更改已經填寫的最後一道樁號資料,可以透過 "上一動 " 將其引入。
6.填寫完後點按 " 結束 " 再進行檢查各項資料後即可儲存備用。
7.進入AutoCAD中,將dvb檔引入後並且將該Excel開啟中,即可繪製一連續的斷面。
8.回到Excel中,點擊 "土石報表 " ,即可得到老大們需要的土石方報表。
' 'This project is to solve the complex and boring things in dredge event 'Made by Hank Lin 2018/3/19 @ MelinStation 'This version is for AutoCAD 2016 and Excel2016 ' Public plineobj As AcadPolyline Public lineobj As AcadLine Public tobj As AcadText Public arcobj As AcadArc Public lay As AcadLayer Const ratio = 1 Const figLength = 4000 Const lastLength = 800 Const txtLength = 2000 Const txtheight100 = 100 * 2.5 Const digWidth = 300 Const rail = 300 Sub getHorizontalFile() Dim spt(2) As Double Dim ept(2) As Double Dim filename As String Dim insertpt() As Double Dim vertices() As Double Dim X_center As Double, Y_center As Double Dim crossName As String, slopeDown As Double, LeftEnv As String, RightEnv As String, bottomDepth As Double, channelType As String, DigArea As Double Dim r As Integer, channelSelect As Integer, BD As Double, BT As Double, H As Double, t As Double, rail As Double, LW As Double, RW As Double, LeftEnvHeight As Double, RightEnvHeight As Double Dim retlineobj1 As AcadLine Dim retlineobj2 As AcadLine Dim ret As Variant Call BasicSetting(1) On Error Resume Next Set excelapp = CreateObject("excel.application") If err <> "" Then Set excelapp = GetObject(, "excel.application") End If On Error GoTo 0 With excelapp On Error GoTo GETFILE '.Workbooks.Open ("D:\Horizontal123.xlsm") On Error GoTo 0 continue: .Visible = True Set sht = excelapp.ActiveWorkbook.ActiveSheet lr = sht.Cells(sht.Rows.Count, 1).End(xlUp).Row ret = ThisDrawing.Utility.GetPoint(, "請選擇第一個渠道要生成的中心點") For r = 3 To lr Step 2 crossName = sht.Cells(r, 1) LeftEnv = sht.Cells(r, 2) LeftEnvHeight = sht.Cells(r, 3) RightEnv = sht.Cells(r, 4) RightEnvHeight = sht.Cells(r, 5) slopeDown = sht.Cells(r, 6) channelType = sht.Cells(r, 7) channelSelect = sht.Cells(r, 7).Font.ColorIndex X_center = ret(0) + figLength * k * 1.5 Y_center = ret(1) + -figLength * j j = j + 1 If j Mod 4 = 0 Then k = k + 1 j = 0 End If i = 3 X = X_center Y = Y_center If channelSelect = 3 Then Call PlotTrapzoidChannel(X, Y, channelType, sht, BD, BT, retlineobj1, retlineobj2, H) Call DigLineT(X, Y, slopeDown, r, sht, BD, retlineobj1, retlineobj2, DigArea) Call DescriptionT(X, Y, LeftEnv, RightEnv, LeftEnvHeight, RightEnvHeight, BT, H) Else Call PlotChannel(X, Y, channelType, sht, BT, LW, RW, t) Call DigLineU(X, Y, slopeDown, r, sht, BT, DigArea) Call DescriptionU(X, Y, LeftEnv, RightEnv, LeftEnvHeight, RightEnvHeight, BT, LW, RW, t) End If Call AddTitle(X, Y, crossName, slopeDown, DigArea) sht.Cells(r, 8) = Round(DigArea / 1000000, 2) Next err: '.Workbooks(1).Close SaveChanges:=True '.Quit End With ZoomAll Exit Sub GETFILE: filename = excelapp.GetOpenFilename If filename Like "False*" Then Exit Sub excelapp.Workbooks.Open (filename) GoTo continue End Sub Sub PlotTrapzoidChannel(ByVal X_center As Double, ByVal Y_center As Double, ByVal channelType As String, ByVal sht As Worksheet, ByRef BD As Double, ByRef BT As Double, _ ByRef retlineobj1 As AcadLine, ByRef retlineobj2 As AcadLine, ByRef H As Double) Dim lineobj As AcadLine, lineobj2 As AcadLine, lineobj3 As AcadLine Dim plineobj As AcadPolyline Dim spt(2) As Double, ept(2) As Double Dim ret1 As Variant, ret2 As Variant Dim vertices(23) As Double ThisDrawing.ActiveLayer = ThisDrawing.Layers("中心線") spt(0) = X_center: spt(1) = Y_center + 800 ept(0) = X_center: ept(1) = Y_center - 300 Set lineobj = ThisDrawing.ModelSpace.AddLine(spt, ept) ThisDrawing.ActiveLayer = ThisDrawing.Layers("原渠道(疏濬)") '---control coefficient---- With sht For Each rng In .UsedRange If rng.Value = "Type" Then c = rng.Column Exit For End If Next r = 3 Do Until .Cells(r, c) = "" If .Cells(r, c) = channelType Then BT = .Cells(r, c + 8) * 1000 BD = .Cells(r, c + 9) * 1000 H = .Cells(r, c + 10) * 1000 t = .Cells(r, c + 11) * 1000 Exit Do End If r = r + 1 Loop m = (BT - BD) / 2 / H '---------------------- spt(0) = X_center: spt(1) = Y_center - t ept(0) = spt(0) - 10: ept(1) = Y_center - t Set lineobj = ThisDrawing.ModelSpace.AddLine(spt, ept) vertices(0) = X_center vertices(1) = Y_center vertices(3) = X_center - BD / 2 vertices(4) = Y_center spt(0) = vertices(3) - t * 1 / Sqr(m * m + 1): spt(1) = vertices(4) - m * t / Sqr(m * m + 1) ept(0) = spt(0) - 200 * m: ept(1) = spt(1) + 200 Set lineobj2 = ThisDrawing.ModelSpace.AddLine(spt, ept) ret1 = lineobj.IntersectWith(lineobj2, acExtendBoth) vertices(6) = X_center - BT / 2 vertices(7) = Y_center + H spt(0) = vertices(3): spt(1) = vertices(4) ept(0) = vertices(6): ept(1) = vertices(7) Set retlineobj1 = ThisDrawing.ModelSpace.AddLine(spt, ept) vertices(9) = X_center - BT / 2 - rail vertices(10) = Y_center + H vertices(12) = X_center - BT / 2 - rail vertices(13) = Y_center + H - t spt(0) = vertices(9): spt(1) = vertices(10) - t ept(0) = spt(0) - 10: ept(1) = spt(1) Set lineobj3 = ThisDrawing.ModelSpace.AddLine(spt, ept) ret2 = lineobj2.IntersectWith(lineobj3, acExtendBoth) vertices(15) = ret2(0) vertices(16) = ret2(1) vertices(18) = ret1(0) vertices(19) = ret1(1) vertices(21) = vertices(0) vertices(22) = vertices(1) - t Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices) spt(0) = X_center spt(1) = Y_center - 100 ept(0) = X_center ept(1) = Y_center Set plineobj2 = plineobj.Mirror(spt, ept) Set retlineobj2 = retlineobj1.Mirror(spt, ept) lineobj.Delete lineobj2.Delete lineobj3.Delete Dim hatchobj As AcadHatch Dim outerloop(0 To 1) As AcadEntity Set hatchobj = ThisDrawing.ModelSpace.AddHatch(0, "SOLID", True) Set outerloop(0) = plineobj Set outerloop(1) = plineobj2 hatchobj.AppendOuterLoop (outerloop) End With End Sub Sub PlotChannel(ByVal X As Double, ByVal Y As Double, ByVal channelType As String, ByVal sht As Worksheet, ByRef BT As Double, ByRef LW As Double, ByRef RW As Double, ByRef t As Double) 'ThisDrawing.ActiveLayer = ThisDrawing.Layers("新建渠道") With sht Dim rng As Range Dim vertices(14 * 3 - 1) As Double Dim spt(2) As Double, ept(2) As Double ThisDrawing.ActiveLayer = ThisDrawing.Layers("中心線") spt(0) = X: spt(1) = Y + 800 ept(0) = X: ept(1) = Y - 300 Set lineobj = ThisDrawing.ModelSpace.AddLine(spt, ept) ThisDrawing.ActiveLayer = ThisDrawing.Layers("原渠道(疏濬)") For Each rng In .UsedRange If rng.Value = "Type" Then c = rng.Column Exit For End If Next lr = .Cells(1, c).End(xlDown).Row For r = 1 To lr If .Cells(r, c) = channelType Then t = .Cells(r, c + 4) * 1000 BT = .Cells(r, c + 3) * 1000 LT = t LW = .Cells(r, c + 5) * 1000 BW = t RW = .Cells(r, c + 6) * 1000 RT = t b = .Cells(r, c + 7) * 1000 Exit For End If Next X_ch = X Y_ch = Y 'pt1 vertices(0) = X_ch vertices(1) = Y_ch 'pt2 vertices(3) = X_ch - BT / 2 vertices(4) = Y_ch 'pt3 vertices(6) = X_ch - BT / 2 vertices(7) = Y_ch + LW 'pt4 vertices(9) = X_ch - BT / 2 - LT vertices(10) = Y_ch + LW 'pt5 vertices(12) = X_ch - BT / 2 - LT vertices(13) = Y_ch 'pt6 vertices(15) = X_ch - BT / 2 - LT - b vertices(16) = Y_ch 'pt7 vertices(18) = X_ch - BT / 2 - LT - b vertices(19) = Y_ch - BW - bW2 'pt8 vertices(21) = X_ch + BT / 2 + RT + b vertices(22) = Y_ch - BW - bW2 'pt9 vertices(24) = X_ch + BT / 2 + RT + b vertices(25) = Y_ch 'pt10 vertices(27) = X_ch + BT / 2 + RT vertices(28) = Y_ch 'pt11 vertices(30) = X_ch + BT / 2 + RT vertices(31) = Y_ch + RW 'pt12 vertices(33) = X_ch + BT / 2 vertices(34) = Y_ch + RW 'pt13 vertices(36) = X_ch + BT / 2 vertices(37) = Y_ch 'pt14 vertices(39) = X_ch vertices(40) = Y_ch Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices) End With Dim hatchobj As AcadHatch Dim outerloop(0 To 0) As AcadEntity Set hatchobj = ThisDrawing.ModelSpace.AddHatch(0, "SOLID", True) Set outerloop(0) = plineobj hatchobj.AppendOuterLoop (outerloop) End Sub Sub AddTitle(ByVal X_center As Double, ByVal Y_center As Double, ByVal crossName As String, ByVal slopeDown As String, ByRef DigArea As Double) ThisDrawing.ActiveLayer = ThisDrawing.Layers("橫斷面說明") Dim txtpt(2) As Double Dim spt(2) As Double Dim ept(2) As Double txtpt(0) = X_center txtpt(1) = Y_center + txtLength txtpt(2) = 0 If crossName Like "*.*" Then crossName = Format(crossName, "0+000.0") Else crossName = Format(crossName, "0+000") End If Set tobj = ThisDrawing.ModelSpace.AddText(crossName, txtpt, txtheight100) tobj.Alignment = acAlignmentMiddleCenter tobj.TextAlignmentPoint = txtpt spt(0) = txtpt(0) - 800 / ratio spt(1) = txtpt(1) - 200 / ratio ept(0) = txtpt(0) + 800 / ratio ept(1) = spt(1) Set lineobj = ThisDrawing.ModelSpace.AddLine(spt, ept) txtpt(1) = Y_center + txtLength - 400 / ratio slopeDown = Format(slopeDown, "0.00") If slopeDown >= 0 Then slopeDown = "-" & slopeDown Set tobj = ThisDrawing.ModelSpace.AddText(slopeDown, txtpt, txtheight100) tobj.Alignment = acAlignmentMiddleCenter tobj.TextAlignmentPoint = txtpt txtpt(0) = txtpt(0) + 2000 txtpt(1) = txtpt(1) + 200 A = "C= " & Round(DigArea / 1000000, 2) & "m3" Set tobj = ThisDrawing.ModelSpace.AddText(A, txtpt, txtheight100) tobj.Alignment = acAlignmentMiddleCenter tobj.TextAlignmentPoint = txtpt 'ThisDrawing.ActiveLayer = ThisDrawing.Layers("0") End Sub Sub DigLineT(ByVal X As Double, ByVal Y As Double, ByVal slopeDown As Double, ByVal r As Integer, _ ByVal sht As Worksheet, ByVal BD As Double, ByVal retlineobj1 As AcadLine, ByVal retlineobj2 As AcadLine, ByRef DigArea As Double) Dim vertices(8 * 3 - 1) As Double Dim ret As Variant Dim spt(2) As Double, ept(2) As Double ThisDrawing.ActiveLayer = ThisDrawing.Layers("開挖線") With sht spt(0) = X - BD / 2: spt(1) = Y + .Cells(r + 1, 1) * 1000 ept(0) = spt(0) - 10: ept(1) = spt(1) + 2 Set lineobj = ThisDrawing.ModelSpace.AddLine(spt, ept) ret = lineobj.IntersectWith(retlineobj1, acExtendBoth) lineobj.Delete vertices(0) = ret(0) vertices(1) = ret(1) vertices(3) = spt(0) vertices(4) = spt(1) spt(0) = X + BD / 2: spt(1) = Y + .Cells(r + 1, 3) * 1000 ept(0) = spt(0) + 10: ept(1) = spt(1) + 2 Set lineobj = ThisDrawing.ModelSpace.AddLine(spt, ept) ret = lineobj.IntersectWith(retlineobj2, acExtendBoth) vertices(6) = X vertices(7) = Y + slopeDown * 1000 vertices(9) = spt(0) vertices(10) = spt(1) vertices(12) = ret(0) vertices(13) = ret(1) vertices(15) = X + BD / 2 vertices(16) = Y vertices(18) = X - BD / 2 vertices(19) = Y vertices(21) = vertices(0) vertices(22) = vertices(1) Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices) DigArea = plineobj.Area lineobj.Delete retlineobj1.Delete retlineobj2.Delete End With End Sub Sub DigLineU(ByVal X As Double, ByVal Y As Double, ByVal slopeDown As Double, ByVal r As Integer, _ ByVal sht As Worksheet, ByVal BT As Double, ByRef DigArea As Double) ThisDrawing.ActiveLayer = ThisDrawing.Layers("開挖線") With sht DigCount = .Cells(r + 1, 1).End(xlToRight).Column - 1 distance = BT / DigCount Dim vertices(8 * 3 - 1) As Double vertices(0) = X - 2 * distance vertices(1) = Y + .Cells(r + 1, 1) * 1000 vertices(3) = X - distance vertices(4) = Y + .Cells(r + 1, 2) * 1000 vertices(6) = X vertices(7) = Y + .Cells(r, 6) * 1000 vertices(9) = X + distance vertices(10) = Y + .Cells(r + 1, 4) * 1000 vertices(12) = X + 2 * distance vertices(13) = Y + .Cells(r + 1, 5) * 1000 vertices(15) = X + 2 * distance vertices(16) = Y vertices(18) = X - 2 * distance vertices(19) = Y vertices(21) = vertices(0) vertices(22) = vertices(1) Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices) DigArea = plineobj.Area End With End Sub Sub DescriptionT(ByVal X As Double, ByVal Y As Double, ByVal LeftEnv As String, ByVal RightEnv As String, ByVal LeftEnvHeight As Double, ByVal RightEnvHeight As Double, ByVal BT As Double, ByVal H As Double) Dim txtpt(2) As Double Dim cpt(2) As Double Dim fitpt(2) As Double Dim basept(2) As Double Dim endpt(2) As Double Dim vertices(3 * 3 - 1) As Double ThisDrawing.ActiveLayer = ThisDrawing.Layers("橫斷面說明") For i = 1 To 2 Select Case i Case 1 basept(0) = X - BT / 2 - rail basept(1) = Y + H fitpt(0) = X - BT / 2 - 2 * rail fitpt(1) = Y + LeftEnvHeight * 1000 endpt(0) = fitpt(0) - lastLength endpt(1) = fitpt(1) txtpt(0) = endpt(0) txtpt(1) = endpt(1) + 200 vertices(0) = basept(0): vertices(1) = basept(1) vertices(3) = fitpt(0): vertices(4) = fitpt(1) vertices(6) = endpt(0): vertices(7) = endpt(1) Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices) Set tobj = ThisDrawing.ModelSpace.AddText(LeftEnv, txtpt, txtheight100) Case 2 basept(0) = X + BT / 2 + rail basept(1) = Y + H fitpt(0) = X + BT / 2 + 2 * rail fitpt(1) = Y + RightEnvHeight * 1000 endpt(0) = fitpt(0) + lastLength endpt(1) = fitpt(1) txtpt(0) = endpt(0) txtpt(1) = endpt(1) + 200 vertices(0) = basept(0): vertices(1) = basept(1) vertices(3) = fitpt(0): vertices(4) = fitpt(1) vertices(6) = endpt(0): vertices(7) = endpt(1) Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices) Set tobj = ThisDrawing.ModelSpace.AddText(RightEnv, txtpt, txtheight100) End Select tobj.Alignment = acAlignmentBottomCenter tobj.TextAlignmentPoint = txtpt Radius = 50 cpt(0) = endpt(0) cpt(1) = endpt(1) + Radius Set arcobj = ThisDrawing.ModelSpace.AddArc(cpt, Radius, 3.14 / 2, -3.14 / 2) arcobj.Rotate endpt, -3.14 / 6 cpt(0) = endpt(0) cpt(1) = endpt(1) - Radius Set arcobj = ThisDrawing.ModelSpace.AddArc(cpt, Radius, -3.14 / 2, 3.14 / 2) arcobj.Rotate endpt, -3.14 / 6 Next 'ThisDrawing.ActiveLayer = ThisDrawing.Layers("0") End Sub Sub DescriptionU(ByVal X As Double, ByVal Y As Double, ByVal LeftEnv As String, ByVal RightEnv As String, ByVal LeftEnvHeight As Double, ByVal RightEnvHeight As Double, ByVal BT As Double, ByVal LW As Double, ByVal RW As Double, ByVal t As Double) Dim txtpt(2) As Double Dim cpt(2) As Double Dim basept(2) As Double Dim spt(2) As Double ThisDrawing.ActiveLayer = ThisDrawing.Layers("橫斷面說明") For i = 1 To 2 Select Case i Case 1 basept(0) = X - BT / 2 - t - lastLength basept(1) = Y + LeftEnvHeight * 1000 txtpt(0) = basept(0) txtpt(1) = basept(1) + 200 spt(0) = basept(0) + lastLength spt(1) = basept(1) Set tobj = ThisDrawing.ModelSpace.AddText(LeftEnv, txtpt, txtheight100) Case 2 basept(0) = X + BT / 2 + t + lastLength basept(1) = Y + RightEnvHeight * 1000 txtpt(0) = basept(0) txtpt(1) = basept(1) + 200 spt(0) = basept(0) - lastLength spt(1) = basept(1) Set tobj = ThisDrawing.ModelSpace.AddText(RightEnv, txtpt, txtheight100) End Select Set lineobj = ThisDrawing.ModelSpace.AddLine(spt, basept) '地盤線 tobj.Alignment = acAlignmentBottomCenter tobj.TextAlignmentPoint = txtpt Radius = 50 cpt(0) = basept(0) cpt(1) = basept(1) + Radius Set arcobj = ThisDrawing.ModelSpace.AddArc(cpt, Radius, 3.14 / 2, -3.14 / 2) arcobj.Rotate basept, -3.14 / 6 cpt(0) = basept(0) cpt(1) = basept(1) - Radius Set arcobj = ThisDrawing.ModelSpace.AddArc(cpt, Radius, -3.14 / 2, 3.14 / 2) arcobj.Rotate basept, -3.14 / 6 Next 'ThisDrawing.ActiveLayer = ThisDrawing.Layers("0") End Sub Sub BasicSetting(ByVal i As Integer) On Error Resume Next Dim txtStyle As AcadTextStyle Dim txtStyles As AcadTextStyles Set txtStyles = ThisDrawing.TextStyles For Each txtStyle In txtStyles If txtStyle.Name = "工程用仿宋體" Then IsAdded = True End If Next If IsAdded = False Then Set txtStyle = txtStyles.Add("工程用仿宋體") txtStyle.fontFile = "c:\windows\fonts\simfang.ttf" End If Set txtStyle = txtStyles("工程用仿宋體") If ThisDrawing.ActiveTextStyle.Name <> "工程用仿宋體" Then ThisDrawing.ActiveTextStyle = txtStyle End If If ThisDrawing.ActiveLayer.Name <> "0" Then ThisDrawing.ActiveLayer = ThisDrawing.Layers("0") End If ThisDrawing.Linetypes.Load "DASHDOT", "acad.lin" ThisDrawing.Linetypes.Load "CENTER", "acad.lin" Set lays = ThisDrawing.Layers Set lay = lays.Add("原渠道(疏濬)") lay.color = acWhite Set lay = lays.Add("中心線") lay.color = acRed lay.Linetype = "CENTER" Set lay = lays.Add("開挖線") lay.color = acGreen Set lay = lays.Add("橫斷面說明") lay.color = acWhite ThisDrawing.ActiveLayer = ThisDrawing.Layers("0") End Sub
前輩請問有檔案可以分享嗎
回覆刪除excel的連結好像失效了
回覆刪除