AutoCADVBA 圖紙小精靈_Ver1.0

前言:

有鑑於大部分前輩的圖都建立於模型空間(ModelSpace)之下,每次畫圖完畢發現少(多)某一張圖,當要插入或者是刪除時,就會需要在圖框內的頁次欄位進行更動,這點可以說是相當麻煩(尤其是對於超過30頁的圖檔來說),因而引發筆者寫這篇Side Project供參考使用。

Demo影片:

使用方法:

1.程式介面建立於VBA之下,為一個dvb檔,有關如何開啟請參考(如何使用dvb檔)。

2.請檢查頁次項目部分為: 第OO頁共OO頁。

3.請檢查圖框圈選線是否為聚合線(連續線段):偵測(LowerLeftPoint,UpperRightPoint)使用。

4.請檢查圖框圈選線所處圖層是否為 ( 出圖圖框 ):過濾圖框項目。

5.執行VBA巨集→點選第一個module(ShowUserForm)→執行。

圖一、紅色部分為圖框圈選線。


按鈕介紹:

1.創造圖框:若需要創建一連串的圖框們,可先在Excel檔中定義圖框內容後批次輸出。

圖二、圖框內容定義

2.新增圖紙:框選所有圖框,輸入要插入的頁次,會把所有框選起來的頁次及>=插入頁次的                           部分批次增加。

3.去除圖紙:框選所有圖框,輸入要刪除的頁次,會把所有框選起來的頁次及>=插入頁次的                           部分批次減少。

4.批次列印:必須先設定列印配置,請參考 (AutoCAD顧問-批次出圖 )

圖三、列印配置

注意事項:先選擇要輸出的印表機→出圖內容改為視窗(要求圈選時先隨意圈選)→置中出圖→比例為1:1→圖面方位(橫式)→如有需要再更改出圖型式表→套用至配置。

檔案下載:

本機端執行環境 AutoCAD2016 x64,Excel2016 x64,下載點: Frame.dvb

原始碼:

UserFrom比較沒東西就不放上來獻醜了。

比較重要的還是Module的部分:(其實是3個module改來改去,我把他合併起來丟上來而已)

Public wrkb As Object
Public wrks As Object
Public objexcel As Object
Public rng As Object
Public plineobj As AcadPolyline
Public lwplineobj As AcadLWPolyline '2D
Public txtobj As AcadText
Public lay As AcadLayer

Sub ShowUserForm()

UserForm1.show

End Sub

Sub ChangeFrame_Main(ByVal method As Integer)

Dim sset As AcadSelectionSet
Dim FilterType(0) As Integer
Dim FilterData(0) As Variant
Dim PlotArr(1 To 100, 1 To 4) As Variant
Dim PlotArrFinal(1 To 100, 1 To 4) As Variant
Dim k As Integer

On Error Resume Next

ThisDrawing.SelectionSets("SS1").Delete

On Error GoTo 0

Set sset = ThisDrawing.SelectionSets.Add("SS1")

FilterType(0) = 8
FilterData(0) = "出圖圖框"

sset.SelectOnScreen FilterType, FilterData

For Each Item In sset

    Dim lwpline As AcadLWPolyline
    
    On Error GoTo ERROR_HANDLE
    
    Set lwpline = Item
        
    k = k + 1
    
    'Debug.Print "第" & k & "項目:"

    max_x = lwpline.Coordinates(0)
    max_y = lwpline.Coordinates(1)
    min_x = lwpline.Coordinates(0)
    min_y = lwpline.Coordinates(1)

    For i = 0 To 7
    
        co = lwpline.Coordinates(i)
        
        If i Mod 2 = 0 Then
        
            X = co
        
            If X > max_x Then max_x = X
        
            If X < min_x Then min_x = X
        
        Else
        
            Y = co
        
            If Y > max_y Then max_y = Y
        
            If Y < min_y Then min_y = Y
        
        End If
    
    Next
     
    PlotArr(k, 1) = max_x 'add data to an array
    PlotArr(k, 2) = max_y
    PlotArr(k, 3) = min_x
    PlotArr(k, 4) = min_y

    'Debug.Print max_x & vbCrLf & max_y & vbCrLf & min_x & vbCrLf & min_y

ERROR_HANDLE:

Next

On Error GoTo 0

Call AddFrame(PlotArr, method)

End Sub

Sub AddFrame(ByRef PlotArrFinal() As Variant, ByVal method As Integer)

Dim LowerLeft(0 To 2) As Double
Dim UpperRight(0 To 2) As Double
Dim sset As AcadSelectionSet
Dim FilterType(0) As Integer
Dim FilterData(0) As Variant

If method = 1 Then

insertnum = InputBox("你要插入第幾張?", "圖紙小精靈對話小框框")

ElseIf method = 2 Then

insertnum = InputBox("你要扣除第幾張?", "圖紙小精靈對話小框框")

End If

insertnum = Val(insertnum)

For i = 1 To 100

    If PlotArrFinal(i, 3) = "" Then Exit For
    
    LowerLeft(0) = PlotArrFinal(i, 1)
    LowerLeft(1) = PlotArrFinal(i, 2)
    UpperRight(0) = PlotArrFinal(i, 3)
    UpperRight(1) = PlotArrFinal(i, 4)
    
    On Error Resume Next
    
    ThisDrawing.SelectionSets("SS1").Delete
    
    On Error GoTo 0
    
    Set sset = ThisDrawing.SelectionSets.Add("SS1")

    FilterType(0) = 0
    FilterData(0) = "Text"

    sset.Select acSelectionSetCrossing, LowerLeft, UpperRight, FilterType, FilterData

    For Each Item In sset
    
        txt = Item.TextString
    
        If txt Like "第*共*" Then
        
            'Debug.Print txt
            
            pt1 = InStr(1, txt, "頁")
            pt2 = InStr(pt1 + 1, txt, "頁")
            
            num1 = Val(Mid(txt, 2, pt1 - 2))
            
            If method = 1 Then
            
                If num1 >= insertnum Then num1 = num1 + 1
                
                num2 = Val(Mid(txt, pt1 + 2, pt2 - (pt1 + 2))) + 1
            
            ElseIf method = 2 Then
            
                If num1 >= insertnum Then num1 = num1 - 1
                
                num2 = Val(Mid(txt, pt1 + 2, pt2 - (pt1 + 2))) - 1
                
            End If
        
            'Debug.Print pt1 & " " & pt2 & " " & num1 & " " & num2
            
            Item.TextString = "第" & num1 & "頁共" & num2 & "頁"
        
        End If
    
    Next

Next

End Sub

Sub CreateFrame_Main(ByVal a As Integer)

Dim txtArr() As Variant
Dim ii As Integer

ret = ThisDrawing.Utility.GetPoint(, "請選擇圖框產生的起始點")

X = ret(0): Y = ret(1)
X_origin = X
Call GetExcel(wrks)

lr = wrks.cells(1, 3).End(-4121).row 'xldown=-4121
lc = wrks.cells(1, 1).End(-4161).column 'xltoright=-4161

ReDim txtArr(1 To lc, 1 To 2)

For r = 2 To lr

    For c = 1 To lc
    
        If wrks.cells(r, c) <> "" Then txtArr(c, 1) = wrks.cells(r, c)
        txtArr(c, 2) = wrks.cells(1, c)
        
    Next
    
    txtArr(lc, 1) = "第" & r - 1 & "頁共" & lr - 1 & "頁"
    
    If r > 2 Then X = X + 500
    
    If ii Mod 10 = 0 And ii <> 0 Then
        
        Y = Y - 500
        X = X_origin
    
    End If
    
    Call PlotFrameOuter(X, Y)
    
    Call PlotFrame(X, Y)
    
    Call PlotFrameInner(X, Y, txtArr)

    ii = ii + 1

Next

End Sub

Sub PlotFrameOuter(ByVal X As Double, ByVal Y As Double)

Dim txtpt(2) As Double
Dim vertices(5 * 2 - 1) As Double

vertices(0) = X - 20
vertices(1) = Y - 10

vertices(2) = X - 20
vertices(3) = Y + 277 + 10

vertices(4) = X + 390 + 10
vertices(5) = Y + 277 + 10

vertices(6) = X + 390 + 10
vertices(7) = Y - 10

vertices(8) = X - 20
vertices(9) = Y - 10

ThisDrawing.ActiveLayer = ThisDrawing.Layers("出圖圖框")

Set lwplineobj = ThisDrawing.ModelSpace.AddLightWeightPolyline(vertices)

ThisDrawing.ActiveLayer = ThisDrawing.Layers("0")

txtpt(0) = X + 300
txtpt(1) = Y - 20

Set txtobj = ThisDrawing.ModelSpace.AddText("出圖圈選範圍線(A3)    297*420", txtpt, 5)

txtobj.color = acRed

End Sub

Sub PlotFrame(ByVal X As Double, ByVal Y As Double)

Dim vertices(5 * 3 - 1) As Double

vertices(0) = X
vertices(1) = Y

vertices(3) = X
vertices(4) = Y + 277

vertices(6) = X + 390
vertices(7) = Y + 277

vertices(9) = X + 390
vertices(10) = Y

vertices(12) = X - 0.8
vertices(13) = Y

Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices)

plineobj.ConstantWidth = 1.6

End Sub

Sub PlotFrameInner(ByVal X As Double, ByVal Y As Double, ByRef txtArr() As Variant)

Dim vertices(3 * 2 - 1) As Double
Dim txtpt(2) As Double

arr = Array(60, 90, 70, 20, 20, 20, 20, 20, 20, 20, 30) '分割長度(由左到右)

For i = 1 To 2

    vertices(0) = X
    vertices(1) = Y + 9.25 * i
    
    vertices(3) = X + 390
    vertices(4) = Y + 9.25 * i
    
    Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices)
    
    plineobj.ConstantWidth = 0.5
    
    Xt = vertices(0)
    
    For j = 0 To UBound(arr)
    
        Xt = Xt + arr(j)
    
        Xtt = Xt - 0.5 * arr(j)
    
        Yt = vertices(1) - 0.5 * 9.25
        
        txtpt(0) = Xtt
        txtpt(1) = Yt
        
        Set txtobj = ThisDrawing.ModelSpace.AddText(txtArr(j + 1, i), txtpt, 3.5) '文字高度3.5
        
        txtobj.Alignment = acAlignmentMiddleCenter
        txtobj.TextAlignmentPoint = txtpt
        
        
    Next
    
Next
    
For j = 0 To UBound(arr) - 1

        X = X + arr(j)
        
        vertices(0) = X
        vertices(1) = Y
        vertices(3) = X
        vertices(4) = Y + 18.5
        Set plineobj = ThisDrawing.ModelSpace.AddPolyline(vertices)
        plineobj.ConstantWidth = 0.5

Next

End Sub

Sub GetExcel(ByRef wrks As Object)

On Error Resume Next

Set objexcel = GetObject(, "Excel.Application")
If Err.Number > 0 Then
    Set objexcel = CreateObject("Excel.Application")
    Err.Clear
End If

Set wrkb = objexcel.ActiveWorkbook
Set wrks = objexcel.ActiveSheet

Set lay = ThisDrawing.Layers.Add("出圖圖框")

lay.color = acRed
lay.ViewportDefault = True

End Sub

Sub PrintOut_Main(ByVal a As Integer)

Dim sset As AcadSelectionSet
Dim FilterType(0) As Integer
Dim FilterData(0) As Variant
Dim PlotArr(1 To 100, 1 To 4) As Variant
Dim PlotArrFinal(1 To 100, 1 To 4) As Variant
Dim k As Integer

On Error Resume Next

ThisDrawing.SelectionSets("SS1").Delete

On Error GoTo 0

Set sset = ThisDrawing.SelectionSets.Add("SS1")

FilterType(0) = 8
FilterData(0) = "出圖圖框"

sset.SelectOnScreen FilterType, FilterData

For Each Item In sset

    Dim lwpline As AcadLWPolyline
    
    On Error GoTo ERROR_HANDLE
    
    Set lwpline = Item
        
    k = k + 1
    
    'Debug.Print "第" & k & "項目:"

    max_x = lwpline.Coordinates(0)
    max_y = lwpline.Coordinates(1)
    min_x = lwpline.Coordinates(0)
    min_y = lwpline.Coordinates(1)

    For i = 0 To 7
    
        co = lwpline.Coordinates(i)
        
        If i Mod 2 = 0 Then
        
            X = co
        
            If X > max_x Then max_x = X
        
            If X < min_x Then min_x = X
        
        Else
        
            Y = co
        
            If Y > max_y Then max_y = Y
        
            If Y < min_y Then min_y = Y
        
        End If
    
    Next
     
    PlotArr(k, 1) = max_x 'add data to an array
    PlotArr(k, 2) = max_y
    PlotArr(k, 3) = min_x
    PlotArr(k, 4) = min_y

    'Debug.Print max_x & vbCrLf & max_y & vbCrLf & min_x & vbCrLf & min_y

ERROR_HANDLE:

Next

On Error GoTo 0

Call SortData(PlotArr, k, PlotArrFinal)

Call PrintOut(PlotArrFinal)

End Sub

Sub SortData(ByRef PlotArr() As Variant, ByVal k As Integer, ByRef PlotArrFinal() As Variant)

    order = 1
    p = 1

    For i = 1 To k
    
        min_x = PlotArr(i, 3)
        
        For j = order To k
        
            order_x = PlotArr(j, 3)
        
            If order_x < min_x Then min_x = order_x
        
        Next
        
        For n = 1 To k
        
            If PlotArr(n, 3) = min_x Then
            
                For z = 1 To 4
                
                    PlotArrFinal(p, z) = PlotArr(n, z) 'min
                    PlotArr(n, z) = PlotArr(i, z)
                    PlotArr(i, z) = PlotArrFinal(p, z)
                
                Next
                
                p = p + 1
                
                Exit For
            
            End If
        
        Next
    
        order = order + 1
    
    Next
    
End Sub

Sub PrintOut(ByRef PlotArrFinal() As Variant)

Dim LowerLeft(0 To 1) As Double
Dim UpperRight(0 To 1) As Double

Dim plotobj As AcadPlot

Dim lay As AcadLayout

Dim IfAsked As Boolean

Set lay = ThisDrawing.ActiveLayout

Set plotobj = ThisDrawing.Plot

'lay.ConfigName = "DWG to PDF.pc3"
'lay.CanonicalMediaName = "ISO_A3_(297.00_x_420.00_MM)"

IfAsked = False

For i = 1 To 100

    If PlotArrFinal(i, 3) = "" Then Exit For
    
    Debug.Print "第" & i & "張圖:列印程序 "
    
    LowerLeft(0) = PlotArrFinal(i, 1)
    LowerLeft(1) = PlotArrFinal(i, 2)
    UpperRight(0) = PlotArrFinal(i, 3)
    UpperRight(1) = PlotArrFinal(i, 4)
    
    lay.CenterPlot = True
    
    lay.PlotType = acWindow
    
    lay.SetWindowToPlot LowerLeft, UpperRight
    
    lay.GetWindowToPlot LowerLeft, UpperRight
    
    If IfAsked = False Then

        plotobj.DisplayPlotPreview acPartialPreview
        msg = MsgBox("請問該測試圖檔是不是正確的?", vbYesNo)
    
    End If
    
    If msg = vbYes Then
    
        plotobj.PlotToDevice

        IfAsked = True
        
    Else
    
        Exit Sub

    End If

Next

End Sub









留言

Popular Posts

Excel VBA @ 監造日報表、查驗表 -2

ExcelVBA@施工照片整理的應用範例

Excel VBA@ 監造日報表、查驗表