|
发表于 2022-7-6 13:21:09
|
显示全部楼层
Hendie,
I think I might have fixed the issues you were having with my code. It seems that on some machines, the viewport is seen by VBA as being an 'IAcadPViewport2' (like on my machine), and an 'IAcadPViewport' (no #2) on others. Weird huh . Anyways, the code looks for that now. I also made these changes:
- Set the UCS for all the viewports and model space to 'World' because it was causing some problems if the UCS was not set to 'World'.
- Added code to delete the selection sets when everything is finished, so you don't have the multiple-runs problem anymore (per your excellent suggestion Hendie ).
Anyways, try out the following code and let me know if it works for you. If not, send me the drawing you are getting errors on and I'll take a look at it to see if I can't get it working.
- 'Returns true if the cleanup was successfully; false if it wasn'tPublic Function cleanupDWG() As Boolean'On Error Resume NextOn Error GoTo ErrorFound 'Variables 'Various objects/array of objects Dim objAcadObject As AcadObject Dim objLayout As AcadLayout Dim objEntities() As AcadEntity 'Add the two selection sets you will be using Dim ss1 As AcadSelectionSet, ssT As AcadSelectionSet Set ss1 = ThisDrawing.SelectionSets.Add("ss1") Set ssT = ThisDrawing.SelectionSets.Add("ssT") 'Points defining the model space points of each viewport Dim arrPoints As Variant: arrPoints = Array(arrPoints, arrPoints) Dim lowerRightP(2) As Double, upperLeftP(2) As Double 'Various counters Dim purgeCount As Integer, vPortsCount As Integer, ssTEntityCount As Integer 'Boolean defining if you are inside the first viewport in a layout (the paperspace itself) Dim boolFirstOne As Boolean: boolFirstOne = True 'Used for filtering only items inside model space Dim FilterData(0) As Variant: Dim DataValue As Variant FilterData(0) = 0: DataValue = FilterData Dim FilterType(0) As Integer: Dim Groupcode As Variant FilterType(0) = 67: Groupcode = FilterType 'Make sure the dynmode is off Call ThisDrawing.SetVariable("DYNMODE", False) 'Make sure that the UCS is set to World inside model space ThisDrawing.ActiveSpace = acModelSpace ThisDrawing.SendCommand "UCS WORLD " 'Go to paper space ThisDrawing.ActiveSpace = acPaperSpace 'Loop through all the layouts For Each objLayout In ThisDrawing.Layouts 'Make sure you aren't in model space If objLayout.Name "Model" Then 'Set the layout to be the active layout ThisDrawing.ActiveLayout = objLayout 'Make sure you are inside paper space before you zoom, then zoom ThisDrawing.MSpace = False ZoomExtents 'Loop through all the objects For Each objAcadObject In objLayout.Block 'If the object name is an MVIEW (either an IAcadPViewPort OR IAcadPViewPort2 in VBA terms) If TypeName(objAcadObject) = "IAcadPViewport" Or TypeName(objAcadObject) = "IAcadPViewport2" Then 'The first one you find will be the actual layout, so skip it If boolFirstOne = True Then 'Set the first viewport found flag to false for the rest of this layout boolFirstOne = False Else 'Go inside model space inside paper space ThisDrawing.MSpace = True 'Make sure that the UCS is set to World inside the viewport ThisDrawing.SendCommand "UCS WORLD " 'Get the points for the selection Call getCrossingBoxPoints(objAcadObject, lowerRightP, upperLeftP) 'Store those points for later use ReDim Preserve arrPoints(vPortsCount + 1) arrPoints(vPortsCount) = lowerRightP: arrPoints(vPortsCount + 1) = upperLeftP vPortsCount = vPortsCount + 2 End If End If Next 'Re-set the first viewport found flag to true for the next layout boolFirstOne = True 'Go outside of model space inside paperspace ThisDrawing.MSpace = False End If Next 'Go to model space and zoom extents so the selection set will work properly ThisDrawing.ActiveSpace = acModelSpace ZoomExtents 'Select everything inside modelspace in a selection set With ThisDrawing.Utility 'Selects everything in model space ss1.Select acSelectionSetAll, , , Groupcode, DataValue End With 'If any viewports were found... If Not IsEmpty(arrPoints(0)) Then 'Loop through the viewport points that were found For vPortsCount = 0 To UBound(arrPoints) Step 2 'Clear the previous selection (if there was one) ssT.Clear 'Get selection set for the viewport using the points found earlier ssT.Select acSelectionSetCrossing, arrPoints(vPortsCount), arrPoints(vPortsCount + 1), Groupcode, DataValue 'If anything was selected... If ssT.Count > 0 Then 'Make space for all the entities in the second selection set ReDim objEntities(ssT.Count - 1) 'Set the objects in the second selection set into the entities array For ssTEntityCount = 0 To ssT.Count - 1 Set objEntities(ssTEntityCount) = ssT(ssTEntityCount) Next 'Remove all the entities from the second selection set from the first selection set ss1.RemoveItems objEntities End If Next 'Delete everything that is still selected ss1.Erase End If 'Delete the selection sets from the drawing ss1.Delete ssT.Delete 'Go to model space ThisDrawing.ActiveSpace = acModelSpace 'zoom extents ZoomExtents 'If you get here, you have succedded. Return true cleanupDWG = TrueExit FunctionErrorFound: 'If the error is because you are trying to remove objects from the 'selection set that were already removed, then continue If Err.Number = -2147467259 Then Resume Next 'If the error is because of any other reason, then return false Else cleanupDWG = False End IfEnd Function'Retrieves the model space lower right and upper left points of the viewportPrivate Sub getCrossingBoxPoints(vp As AcadPViewport, lowerRightP() As Double, upperLeftP() As Double)On Error GoTo ErrorFound 'Variables Dim lowerLeftP As Variant, upperRightP As Variant Dim paperViewHeight As Double, paperViewWidth As Double 'Set the viewport to the current view port ThisDrawing.ActivePViewport = vp 'Get the min and max lower left and upper right points in paper space terms Call vp.GetBoundingBox(lowerLeftP, upperRightP) 'Translate the paper space points to model space points lowerLeftP = ThisDrawing.Utility.TranslateCoordinates(lowerLeftP, acPaperSpaceDCS, acDisplayDCS, False) upperRightP = ThisDrawing.Utility.TranslateCoordinates(upperRightP, acPaperSpaceDCS, acDisplayDCS, False) lowerLeftP = ThisDrawing.Utility.TranslateCoordinates(lowerLeftP, acDisplayDCS, acWorld, False) upperRightP = ThisDrawing.Utility.TranslateCoordinates(upperRightP, acDisplayDCS, acWorld, False) 'Set the lower right and upper left points of the view as they would be in model space lowerRightP(0) = upperRightP(0) lowerRightP(1) = lowerLeftP(1) upperLeftP(0) = lowerLeftP(0) upperLeftP(1) = upperRightP(1)Exit SubErrorFound: 'Error occured. Tell user and exit the program. MsgBox "Error occured in private sub getCrossingBoxPoints! Exiting program...", _ vbCritical + vbOKOnly, "Error!!!" EndEnd Sub
Thanks,
Brian Wiggins |
|