Hi folks,
i have been thinking for several days how to implement a VBA program that can generate shapes from data entered on a worsksheet.
Basically, it is to analyse the filling of cable trays with cables.
The user will enter cable diameters, and the tray width ( e.g 300mm).
Depending on the diameter the program will generate circles with according diameter on a tray .
All should be to scale.
Circles has to be side by side ( which to me is the most difficult part), and can be on 1,2 or 3 layers ( slectable by the user on a form).
I am at the evaluation stage, and thinking if it will not be easier using VISIO, but i never tried vba on visio, or , from an excel WS, generate a script that can be exported in Autocad ???
I am working on the excel solution only, but any ideas are welcome. I just started in VBA with shapes, so not sure if it is the correct way to go for my project.
Thanks for your feedback.![]()
I would suggest that if you have access to AutoCAD, tackle the problem from there.
AutoCAD can scale blocks, position them, and put them on layers of your choice. That's what it's for.
AutoCAD uses VBa and can be programmed to read an Excel file but it is easier to read a CSV.
Shapes in Excel are not, in my opinion, the easiest thing in the world to control so if you don't need the Excel Sheet to show graphic, go the AutoCAD route.
You can always use the AutoCAD result for a display in Excel.
Just an opinion.
I didn't know AutoCAD supported VBA ... huh.
One advantage of using Visio is that it has a macro recorder. I've never automated Visio (and never used AutoCAD), and so can't make an informed recommendation, but I suspect Visio would be easier if the problem is more drawing-oriented, and AutoCAD if the problem is more CAD-oriented.
Microsoft MVP - Excel
Entia non sunt multiplicanda sine necessitate
As of Release 14 AutoCAD supports use of VBA and there are code snippets available via a web search as well as tutorials. However, though VBA is supported, they are moving toward support of .NET.
I agree with Marcol - skip Excel and work directly within AutoCAD.
Strictly speaking, Visio doesn't support layers like CAD, but (sort of) simulates layers by allowing a background sheet for common page elements and each sheet is, like Excel, independent from other sheets.
AutoCAD VBA Support
Palmetto
Do you know . . . ?
You can leave feedback and add to the reputation of all who contributed a helpful response to your solution by clicking the star icon located at the left in one of their post in this thread.
Visio does support named layers, and independent control (e.g., visibility) for each.Visio doesn't support layers like CAD
Microsoft MVP - Excel
Entia non sunt multiplicanda sine necessitate
I may have misspoken on that point, but the PC I'm on now doesn't have Visio and I don't typically need layers. Does the layer features exist in pre-2007 versions?Visio does support named layers, and independent control (e.g., visibility) for each.
Palmetto
Do you know . . . ?
You can leave feedback and add to the reputation of all who contributed a helpful response to your solution by clicking the star icon located at the left in one of their post in this thread.
I only have 2007 now, P, but recollect it existed at least back to 2002.
Microsoft MVP - Excel
Entia non sunt multiplicanda sine necessitate
AutoCAD has supported VBa since R14 (1997) prior to that the language was AutoLisp & with great difficulty DIESEL.
It is not unlike VBa in MSoffice but with obviously many specialised commands. It has an annoying ability to use commands very similar to office in slightly different ways and can cause great frustration when working on the two systems at the same time.
AutoCAD is possibly the most versitle drawing system commonly available. The ability to programme it with VBa means it is extremely flexible.
The scaling aspect is not easily done in Visio nor is the drawing when compared to AutoCAD.
Layers are not inherent in Visio although they can be simulated with VBa
I do all of my more complicated drawings for Visio in AutoCAD then import them and tweak to suit.
If it was me, I'd go the AutoCAD route.
Layers are not inherent in VisioCode:With Application.ActiveWindow.Page .Layers.Add ("Marcol") .Layers.Add ("Palmetto") .Shapes.ItemFromID(1).CellsSRC(visSectionObject, visRowLayerMem, visLayerMember).FormulaForceU = """0""" .Shapes.ItemFromID(2).CellsSRC(visSectionObject, visRowLayerMem, visLayerMember).FormulaForceU = """1""" End With
Microsoft MVP - Excel
Entia non sunt multiplicanda sine necessitate
Sorry shg I was comparing Visio to AutoCAD which has infinitely more control
I have probably missed the potential of Visio layers because of this.
Last edited by Marcol; 03-20-2010 at 02:15 PM. Reason: spelling
I don't doubt that. Visio is an office (small o) drawing program. I know some AutoCAD wizards, and they do amazing stuff in 3D.I was comparing Visio to AutoCAD which has infinitely more control
Microsoft MVP - Excel
Entia non sunt multiplicanda sine necessitate
Thanks All for your advices.
However i may miss explained the "layers " i am talking about.
I mean layers on the Tray itself, so all shapes will be on the same plane area. I should have said "rows" instead.
As for my project i will limit the rows to 3 maximum per tray.
AutoCAD is surely the best way to go when you are comfortable with scripts. I also not sure how to arrange the circles side by side, of different diameter .
Another pb i think, is that it requires to have two programs to make it work,not very " professionnal", but if there is no other way, i will work on it.
Thanks again for your critcial advices.
Hi,
Not sure if this will help your cause.. but the attached is something I use to draw proportinate venn diagrams.
You may be able to pull apart and tweak for your needs.
It draws circles and positions them correctly.
Hi Breizh29
I use Drawing Exchange Format (DXF) file then open and reference the file in AutoCad .
with dxf you can set the layers and shapes lines text ect....
regards pike
If the solution helped please donate here to the RSPCA
Sites worth visiting;
J&R Solutions - royUK
AJP Excel Information - Andy Pope
Spreadsheet Toolbox
JBeaucaires Excel Files
VBA for smarties - snb
Hi Breizh29
This might be worth a try.
The resulting drawing is very basic but it should be enough to demonstrate the principle.
1/. Open AutoCAD
2/. Press Alt + f11 to open the visual basic editor
Or Tools > Macros > Visual Basic Editor
3/. In the Editor
Insert > Module
4/. Copy and paste all of the code below into this empty module.
5/- Change this Sub to suit the full path name to where you have stored the Sample Excel File attached.
5/. Close the editor.Code:Sub DrawCables() DrawCablesFromExcelFile "C:\Users\Alistair\AutoCAD\CableTrays.XLS", "Sheet1" End Sub
6/. In AutoCAD
Press Alt + f8 to open the Macro Dialogue Box
Or Tools > Macro > Macros........
There will only be one Macro. Select it and Press Run
This routine will open Excel and open file CableTrays.XLS,
Loop through the table, draw each tray and fill it with cables to capacity of the tray.
The number of rows, number of cables per row/layer, and the total number of cables are entered in Excel
If Excel was open when the macro was run it will leave Excel open.
if not it will close the Application.
The cables are *stacked" not "nested" and are allowed to protrude above the tray lip by up to 50% of the cable diameter.
The code is a "mixture" of the two VBa types.
Code:' Required API routines: Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _ ByVal lpWindowName As Long) As Long Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Sub DrawCables() DrawCablesFromExcelFile "C:\Users\Alistair\AutoCAD\CableTrays.XLS", "Sheet1" End Sub Sub DrawCablesFromExcelFile(FileNameAndPath As String, SheetName As String) Dim MyXL As Object Dim ExcelFound As Boolean ' Check if Excel is running. On Error Resume Next Set MyXL = GetObject(, "Excel.Application") If Err.Number <> 0 Then ExcelFound = True Err.Clear ' Clear Err object in case error occurred. ExcelFound = DetectExcel ' Set the object variable to reference the file you want to use. Set MyXL = GetObject(FileNameAndPath) ' Show Microsoft Excel. MyXL.Application.Visible = True MyXL.Parent.Windows(1).Visible = True ' Draw in AutoCAD Dim TrayWidth As Double, TrayHeight As Double, CableDia As Double, offsetY As Double Dim r As Integer offsetY = 0 r = 2 With MyXL.sheets(SheetName) .Activate Do TrayWidth = CDbl(.cells(r, "A")) TrayHeight = CDbl(.cells(r, "B")) CableDia = CDbl(.cells(r, "C")) NoRows = Int(TrayHeight / CableDia) If TrayHeight Mod CableDia >= CableDia / 2 Then NoRows = NoRows + 1 End If NoCols = Int(TrayWidth / CableDia) ' Enter in Excel .cells(r, "D") = NoRows .cells(r, "E") = NoCols .cells(r, "F") = NoRows * NoCols DrawTray TrayWidth, TrayHeight, offsetY DrawCableArray TrayWidth, TrayHeight, CableDia, offsetY offsetY = offsetY - (2 * TrayHeight) r = r + 1 If .cells(r, "A") = "" Then Exit Do Loop End With ZoomAll ' If Excel was not open Close Excel else leave it open If Not ExcelFound Then MyXL.Application.Quit End If ' Release reference Excel and spreadsheet. Set MyXL = Nothing End Sub Function DetectExcel() As Boolean ' Function to dectect a running Excel instance and register it. Const WM_USER = 1024 Dim hWnd As Long ' If Excel running - API call to returns its handle. hWnd = FindWindow("XLMAIN", 0) If hWnd = 0 Then ' 0 = Excel not running. DetectExcel = False Exit Function Else ' Excel is running - SendMessage API enters it in the Running Object Table. SendMessage hWnd, WM_USER + 18, 0, 0 DetectExcel = True End If End Function Private Sub DrawTray(TrayWidth As Double, TrayHeight As Double, offsetY As Double) Dim aline As AcadLine Dim startPt(0 To 2) As Double Dim endPt(0 To 2) As Double 'TrayBase startPt(0) = 0#: startPt(1) = offsetY: startPt(2) = 0# endPt(0) = TrayWidth: endPt(1) = offsetY: endPt(2) = 0# Set aline = ThisDrawing.ModelSpace.AddLine(startPt, endPt) aline.Update 'TrayWalls endPt(0) = 0#: endPt(1) = TrayHeight + offsetY: endPt(2) = 0# Set aline = ThisDrawing.ModelSpace.AddLine(startPt, endPt) aline.Update startPt(0) = TrayWidth: startPt(1) = offsetY: startPt(2) = 0# endPt(0) = TrayWidth: endPt(1) = TrayHeight + offsetY: endPt(2) = 0# Set aline = ThisDrawing.ModelSpace.AddLine(startPt, endPt) aline.Update End Sub Private Sub DrawCableArray(TrayWidth As Double, TrayHeight As Double, CableDia As Double, offsetY As Double) Dim cCable As AcadCircle Dim Centre(0 To 2) As Double Dim Radius As Double, CableOffset As Double Radius = CableDia / 2 CableOffset = Int(TrayWidth / CableDia) * CableDia CableOffset = (TrayWidth - CableOffset) / 2 'Draw first Cable Centre(0) = Radius + CableOffset: Centre(1) = Radius + offsetY: Centre(2) = 0# Set cCable = ThisDrawing.ModelSpace.AddCircle(Centre, Radius) cCable.Update ' Define the Cable Array Dim NoRows As Long Dim NoCols As Long Dim NoLevels As Long Dim offsetRows As Double Dim offsetCols As Double Dim offsetLevels As Double NoRows = Int(TrayHeight / CableDia) If TrayHeight Mod CableDia >= CableDia / 2 Then NoRows = NoRows + 1 End If NoCols = Int(TrayWidth / CableDia) NoLevels = 2 offsetRows = CableDia offsetCols = CableDia offsetLevels = 1 ' Create the array of objects Dim retObj As Variant retObj = cCable.ArrayRectangular(NoRows, NoCols, NoLevels, offsetRows, offsetCols, offsetLevels) ThisDrawing.Regen acActiveViewport End Sub
I have only tried this in AutoCAD 2005 and Excel 2003, but it should be okay in other versions.
Hope this might be of some help.
Last edited by Marcol; 03-21-2010 at 05:16 PM. Reason: Clarification of description
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks