I want to change an already working macro that lists the part number and name of the protections in a listbox.Now I also try to list length of each protection that I can find in my cable. I looked it up and people told me you cannot access electrical properties of a protection where I can get the lenght, therefore I need to make a workarround. First I need to create a parameter for each protection. Then create a formula (length on curve and 2 points)to feed the parameter. Then list the value in a listbox.
selection1.Search "CATElectricalSearch.Protection,all"
Dim i As Integer
Dim oInstProd As Product
Dim strpartno As String
For i = 1 To selection1.Count
Set oInstProd = selection1.Item(i).LeafProduct
strpartno = oInstProd.ReferenceProduct.PartNumber
'test
selection1.Item(1).Document.Activate
Dim part1 As Part
Set part1 = selection1.Item(1).Document.Part
Dim parameters1 As Parameters
Set parameters1 = part1.Parameters
On Error Resume Next
Err.Clear 'Clear any previous error messages
Set ParamV = parameters1.Item("Lungime")
If Err.Number = 0 Then
parameters1.Remove "Lungime"
Else
'TODO Stuff if parameter does not Exist
'create a new length type parameter, set its value to 0 for now
Dim length1 As Dimension
Set length1 = parameters1.CreateDimension("", "LENGTH", 0)
'if you want to rename the parameter
length1.Rename "Lungime"
Dim hybridBodies1 As HybridBodies
Set hybridBodies1 = part1.HybridBodies
Dim hybridBody1 As HybridBody
Set hybridBody1 = hybridBodies1.Item("External References")
Set hybridShapes1 = hybridBody1.HybridShapes
Dim reference1 As Reference
Set reference1 = hybridShapes1.Item(1) 'get curve
Dim reference2 As Reference
Set reference2 = hybridShapes1.Item(2) 'get first point
Dim reference3 As Reference
Set reference3 = hybridShapes1.Item(3) 'get second point
'create a new formula to link to the parameter
Dim relations1 As Relations
Set relations1 = part1.Relations
'make sure points are labeled MyEndPt1 and MyEndPt2 respectively
Dim formula1 As Formula
Set formula1 = relations1.CreateFormula("Formula.47", "", length1, "length( `External References\" & reference1.Name & "` ,`External References\" & reference2.Name & "` , `External References\" & reference3.Name & "` ) ")
'MsgBox length1.ValueAsString
End If
'end test
With UserFormTapeCheck.ListBox1
.AddItem
.List(i - 1, 0) = selection1.Item(i).LeafProduct.Name
.List(i - 1, 1) = strpartno
'test
.List(i - 1, 2) = length1.ValueAsString
'end test
End With
'test
relations1.Remove "Formula.47"
parameters1.Remove "Lungime"
'end test
Next
selection1.Clear
The macro works perfect if I only list the part number and leafproduct.name.
I need to get inside the part. Think I am still inside the product and therefore macro can't get the parameters nor the hybrid bodies.
I manage to make to make it work. Found the way to get the part from a electrical component Set oPart = oInstProd.ReferenceProduct.Parent.Part
Dim productDocument1 As ProductDocument
Set productDocument1 = CATIA.ActiveDocument
Dim selection1 As Selection
Set selection1 = productDocument1.Selection
selection1.Search "CATElectricalSearch.Protection,all"
Dim i As Integer
Dim oInstProd As Product
Dim strpartno As String
Dim oPart As Part
For i = 1 To selection1.Count
Set oInstProd = selection1.Item(i).LeafProduct
strpartno = oInstProd.ReferenceProduct.PartNumber
'test
Set oPart = oInstProd.ReferenceProduct.Parent.Part
Dim parameters1 As Parameters
Set parameters1 = oPart.Parameters
On Error Resume Next
Err.Clear 'Clear any previous error messages
Set ParamV = parameters1.Item("Lungime")
If Err.Number = 0 Then
parameters1.Remove "Lungime"
Else
'TODO Stuff if parameter does not Exist
'create a new length type parameter, set its value to 0 for now
Dim length1 As Dimension
Set length1 = parameters1.CreateDimension("", "LENGTH", 0)
'if you want to rename the parameter
length1.Rename "Lungime"
Dim hybridBodies1 As HybridBodies
Set hybridBodies1 = oPart.HybridBodies
Dim hybridBody1 As HybridBody
Set hybridBody1 = hybridBodies1.Item("External References")
Set hybridShapes1 = hybridBody1.HybridShapes
Dim reference1 As Reference
Set reference1 = hybridShapes1.Item(1) 'get curve
Dim reference2 As Reference
Set reference2 = hybridShapes1.Item(2) 'get first point
Dim reference3 As Reference
Set reference3 = hybridShapes1.Item(3) 'get second point
'create a new formula to link to the parameter
Dim relations1 As Relations
Set relations1 = oPart.Relations
'make sure points are labeled MyEndPt1 and MyEndPt2 respectively
Dim formula1 As Formula
Set formula1 = relations1.CreateFormula("Formula.47", "", length1, "length( `External References\" & reference1.Name & "` ,`External References\" & reference2.Name & "` , `External References\" & reference3.Name & "` ) ")
End If
'end test
With UserFormTapeCheck.ListBox1
.AddItem
.List(i - 1, 0) = selection1.Item(i).LeafProduct.Name
.List(i - 1, 1) = strpartno
'test
.List(i - 1, 2) = Round(Abs(length1.Value), 2)
'end test
End With
'test
relations1.Remove "Formula.47"
parameters1.Remove "Lungime"
'end test
Next
selection1.Clear
Found another way to do it. In the relations there are some values saved , like: length of the electrical route and the distances from the each end of the route. With this 3 values you can calculate the length of the protection.
selection1.Search "CATElectricalSearch.Protection,all"
Dim i As Integer
Dim oInstProd As Product
Dim strpartno As String
Dim oPart As Part
Dim routelength As Double
Dim parameters1 As Parameters
Dim ParamPoint4 As Dimension
Dim ParamPoint3 As Dimension
Dim ParamTotal As Dimension
For i = 1 To selection1.Count
Set oInstProd = selection1.Item(i).LeafProduct
strpartno = oInstProd.ReferenceProduct.PartNumber
'test
Set oPart = oInstProd.ReferenceProduct.Parent.Part
Set parameters1 = oPart.Parameters
Set ParamPoint4 = parameters1.Item("ElecRouteBody.1\Point.4\Length.2")
Set ParamPoint3 = parameters1.Item("ElecRouteBody.1\Point.3\Length.1")
Set ParamTotal = parameters1.Item(oPart.Name & "\Elec_Length")
routelength = ParamTotal.Value - ParamPoint4.Value - ParamPoint3.Value
With UserFormTapeCheck.ListBox1
.AddItem
.List(i - 1, 0) = selection1.Item(i).LeafProduct.Name
.List(i - 1, 1) = strpartno
'test
.List(i - 1, 2) = Round(routelength, 2)
'end test
End With
I also encountered some small problems where the Elec_Length had a wrong value and I had to deleted & place the protection again for it to be updated and the macro to draw the correct values. For now I'm very pleased with how it turned out. Enjoy
Related
Here is the code:
numLoansSoldPrev = Range("LoansSold:NewHedges").Cells.Count
If numLoansSoldPrev > 3 Then
Set rngLoansSoldStart = ActiveWorkbook.Sheets("Email").Range("LoansSold").Offset(1, 1)
Let strLoansSoldStart = rngLoansSoldStart.Address
Set rngLoansSoldEnd = ActiveWorkbook.Sheets("Email").Range("NewHedges").Offset(-2, 5)
Let strLoansSoldEnd = rngLoansSoldEnd.Address
Range(strLoansSoldStart & ":" & strLoansSoldEnd).Select
Selection.ClearContents
End If
The commands below the beginning of the if statement work just fine on their own, but every time I try to execute this, I get "block if without end if" despite clearly having one at the bottom.
I have numerous of these if statements in the file but they are all in the same format, so it's not like one if statement is missing an end if.
Any idea?
Expanded Code:
' DECLARE NEW LONGS VARIABLES
Dim numNewLoansPrev As Integer
Dim rngLoansStart As Range
Dim rngLoansEnd As Range
Dim strLoansStart As String
Dim strLoansEnd As String
' DECLARE NEW LOANS SOLD VARIABLES
Dim numLoansSoldPrev As Integer
Dim rngLoansSoldStart As Range
Dim rngLoansSoldEnd As Range
Dim strLoansSoldStart As String
Dim strLoansSoldEnd As String
' DECLARE NEW HEDGES VARIABLES
Dim numNewHedges As Integer
Dim rngNewHedgesStart As Range
Dim rngNewHedgesEnd As Range
Dim strNewHedgesStart As String
Dim strNewHedgesEnd As String
Dim xcess As Integer
' Active E-mail Tab
Worksheets("Email").Activate
' CLEAR EXCESS NEW LONG POSITIONS
numNewLoansPrev = Range("NewLongs:LoansSold").Cells.Count
If numNewLoansPrev > 3 Then
Set rngLoansStart = ActiveWorkbook.Sheets("Email").Range("NewLongs").Offset(1, 1)
Set strLoansStart = rngLoansStart.Address
Set rngLoansEnd = ActiveWorkbook.Sheets("Email").Range("LoansSold").Offset(-2, 5)
Set strLoansEnd = rngLoansEnd.Address
Range(strLoansStart & ":" & strLoansEnd).Select
Selection.ClearContents
End If
' CLEAR EXCESS SOLD LONG POSITIONS
numLoansSoldPrev = Range("LoansSold:NewHedges").Cells.Count
If numLoansSoldPrev > 3 Then
Set rngLoansSoldStart = ActiveWorkbook.Sheets("Email").Range("LoansSold").Offset(1, 1)
Set strLoansSoldStart = rngLoansSoldStart.Address
Set rngLoansSoldEnd = ActiveWorkbook.Sheets("Email").Range("NewHedges").Offset(-2, 5)
Set strLoansSoldEnd = rngLoansSoldEnd.Address
Range(strLoansSoldStart & ":" & strLoansSoldEnd).Select
Selection.ClearContents
End If
' CLEAR EXCESS NEW HEDGES POSITIONS
numNewHedges = Range("NewHedges:Pnl").Cells.Count
If numNewHedges > 3 Then
Set rngNewHedgesStart = ActiveWorkbook.Sheets("Email").Range("NewHedges").Offset(1, 1)
Set strNewHedgesStart = rngNewHedgesStart.Address
Set rngNewHedgesEnd = ActiveWorkbook.Sheets("Email").Range("PnL").Offset(-2, 5)
Set strNewHedgesEnd = rngNewHedgesEnd.Address
Range(strNewHedgesStart & ":" & strNewHedgesEnd).Select
Selection.ClearContents
End If
I have a bunch of Comboboxes (ActiveX elements) and want to loop through all of them to fill them if there's an x next to it and empty them if there is not. This already works, but I'm getting an error when I try clearing the text/value of the the combobox after it has been emptied. Any ideas why?
Dim ws2 as worksheet
Dim ComBx As OLEObject
Dim Name As String
Dim NameParaWS3
Dim ComboFill As Range
Dim VisibleFill As Range
For Each ComBx In ws2.OLEObjects
ComBx.ListFillRange = ""
If ComBx.progID Like "Forms.ComboBox.1" Then
If ws2.Cells(ComBx.TopLeftCell.row, AlphaCol).Value = "X" Then
Name = ws2.Cells(ComBx.TopLeftCell.row, 2).Value
Set NameParaWS3 = ws3.Range("1:1").Find(Name, LookAt:=xlWhole)
Set ComboFill = ws3.Range(ws3.Cells(2, NameParaWS3.Column), ws3.Cells(LastRow3, NameParaWS3.Column))
Set VisibleFill = ComboFill.SpecialCells(xlCellTypeVisible)
Debug.Print ComBx.Name & " located at " & ComBx.TopLeftCell.Address(False, False, xlA1) & ", belongs to parameter '" & Name & "' and is alphanumeric"
With ComBx
.ListFillRange = ComboFill.Address(0, 0, xlA1, True)
End With
Else: ComBx.ListFillRange = ""
'This is the part where I'm getting the error.None of these worked:
'ComBx.Clear
'ComBx.Value = ""
'ComBx.Text= ""
End If
End If
Next ComBx
Use the .Object property of the OLEObject to retrieve the ComboBox object and its usual methods.
ComBx.Object.value = ""
You can even dim a variable a Combobox and have Intellisense for its methods:
Dim cmb as ComboBox: Set cmb = ComBx.Object
cmb.value = ""
I have got a code to generate PowerPoint with an Excel file. I have mostly modified the code as per my requirement, but I want to add one more feature into my .ppt. I want VBA to extract Week Number from some source and do the following:
Rename my .ppt as "XXX_Weeknumber.ppt"
In one of the textboxes in the slides I want to add the same Weeknumber.
I tried getting the week number by using the function WeekNum and trying to call the function in my Main Sub but unfortunately doesn't work!
My code for function in Module 1:
Function WeekNum(D As Date) As Integer
WeekNum = CInt(Format(D, "ww", 2))
End Function
Code for the .xls to .ppt in Module 2:
Dim oPPTApp As PowerPoint.Application
Dim oPPTShape As PowerPoint.Shape
Dim oPPTShape2 As PowerPoint.Shape
Dim oPPTFile As PowerPoint.Presentation
Dim PPSlide As PowerPoint.slide
Dim SlideNum As Integer
Dim rng As Range
Dim WeekNumm$
Sub PPTableMacro()
Dim sourcexl As Workbook
Dim wk As Integer
Dim strPresPath As String, strExcelFilePath As String, strNewPresPath As String
strExcelFilePath = "C:\MySource.xls"
strPresPath = "C:\Presentation1.ppt"
Call WeekNum
WeekNumm = WeekNum()
Set wk = WeekNumm
strNewPresPath = "C:\Presentation1_" & wk & ".ppt" 'This is how I want the name
strNewPresPath = "C:\new1.ppt"
Set oPPTApp = CreateObject("PowerPoint.Application")
oPPTApp.Visible = msoTrue
Set oPPTFile = oPPTApp.Presentations.Open(strPresPath)
SlideNum = 2
oPPTFile.Slides(SlideNum).Select
Set oPPTShape = oPPTFile.Slides(SlideNum).Shapes("Table 1")
Set sourcexl = Workbooks.Open(strExcelFilePath) 'Source excel file
With sourcexl
.Sheets("Sheet1").Activate
oPPTShape.Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = Cells(1, 1).Text
oPPTShape.Table.Cell(1, 2).Shape.TextFrame.TextRange.Text = Cells(1, 2).Text
oPPTShape.Table.Cell(1, 3).Shape.TextFrame.TextRange.Text = Cells(1, 3).Text
oPPTShape.Table.Cell(2, 1).Shape.TextFrame.TextRange.Text = Cells(2, 1).Text
oPPTShape.Table.Cell(2, 2).Shape.TextFrame.TextRange.Text = Cells(2, 2).Text
oPPTShape.Table.Cell(2, 3).Shape.TextFrame.TextRange.Text = Cells(2, 3).Text
End With
Set oPPTShape2 = oPPTFile.Slides(SlideNum).Shapes("TextBox 1")
Text1 = "weekXX" ' actually wanted week number here
oPPTShape2.TextFrame.TextRange.Text = Text1
oPPTFile.SaveAs strNewPresPath
'oPPTFile.Close
'oPPTApp.Quit
Set oPPTShape = Nothing
Set oPPTFile = Nothing
Set oPPTApp = Nothing
MsgBox "Presentation Created", vbOKOnly + vbInformation
End Sub
Your function asks for a data input ("D"), and it's not optional. If you want to retrieve the day of the week of today ("Date" system variable), you should call it like this:
WeekNumm = WeekNum(Date)
Also, you are using a Set statement in "Set wk = WeekNumm". As the variable isn't an object, you have to use (a preferably omitted) Let.
Also, your function will not return the day of the week, because "ww" means the week number of the year. If you want the day of the week by this approach, you have to use "w".
For a better approach, you should use the builtin function Weekday to get the weekday.
Like:
iWeekDay = Weekday(Date,vbUseSystemDayOfWeek) 'Retrieves today's day of the week (Tuesday = 3...)
I am trying to create a VB macro in Visio that can read the data and properties of the shape. So say I have a Rectangle Shpae in Visio with Cells Name, Description, Type, Size.... and so on.
When I try to read the cells and their values I am only getting the first cell and its value.
Here is my code . I would appreciate some help here.
Sub Testing()
Dim excelObj As Object
Dim excelFile As String
Dim sheetName As String
' Dim excelBook As Excel.Workbook
' Set excelFile = "C:\Users\hbhasin\Documents\test.xls"
'Set sheetName = "New Sheet name"
Set excelObj = CreateObject("Excel.Application")
excelObj.Workbooks.Add
Dim pagObj As Visio.Page
Dim shpsObj As Visio.shapes
Dim shapes As Visio.shapes
Dim shpObj As Visio.Shape
Dim CellObj As Visio.Cell
Dim Storage() As String
Dim iShapeCount As Integer
Dim i As Integer
Dim j As Integer
Set pagObj = ActivePage
Set shpsObj = pagObj.shapes
iShapeCount = shpsObj.Count
Debug.Print iShapeCount
ReDim Storage(8, iShapeCount - 1)
For i = 1 To iShapeCount - 1
Set shpObj = shpsObj(i)
Storage(1, i - 1) = shpObj.Name
If shpObj.CellExists("Prop.Name", visExistsLocally) Then
Set CellObj = shpObj.CellsU("Prop.Name")
Storage(2, i - 1) = CellObj.ResultStr("")
End If
If shpObj.CellExists("Prop.Description", visExistsLocally) Then
Debug.Print "Test the IF statement"
Set CellObj = shpObj.CellsU("Prop.Description")
Storage(3, i - 1) = CellObj.ResultStr("")
End If
Next
For i = 0 To iShapeCount - 1
Debug.Print "Name- " & Storage(0, i)
Debug.Print "Description-" & Storage(1, i)
Next
End Sub
In fact, I have put a debug statement within the second if clause and that does not execute which tells me the compiler is not even seeing the second cell or any cell after.
If you're not getting the Description Shape Data it maybe that it's not local, but inherited from its master. Here's a slight modification of your code (with the Excel part removed as I don't think it's relevant here):
Sub Testing()
Dim shpsObj As Visio.shapes
Set shpsObj = ActivePage.shapes
Dim iShapeCount As Integer
iShapeCount = shpsObj.Count
'Assumes you want an array of shape data
Dim Storage() As String
ReDim Storage(iShapeCount - 1, 2)
'Visio shapes are 1 based so use full count
Dim i As Integer
Dim shpObj As Visio.Shape
For i = 1 To iShapeCount
Set shpObj = shpsObj(i)
Storage(i - 1, 0) = shpObj.Name 'Do you want NameU?
'Assumes you don't care whether the cell is local or inherited
If shpObj.CellExistsU("Prop.Name", visExistsAnywhere) Then
Storage(i - 1, 1) = shpObj.CellsU("Prop.Name").ResultStr("")
End If
If shpObj.CellExistsU("Prop.Description", visExistsAnywhere) Then
Storage(i - 1, 2) = shpObj.CellsU("Prop.Description").ResultStr("")
End If
Next
Dim j As Long
For j = LBound(Storage, 1) To UBound(Storage, 1)
Debug.Print "Shape Name- " & Storage(j, 0)
Debug.Print " Prop.Name- " & Storage(j, 1)
Debug.Print " Prop.Description- " & Storage(j, 2)
Next j
End Sub
If you're just running through all the shapes on the page, then you might want to look at For Each shp In shapes as an alternative. Check out this page for more details:
http://visualsignals.typepad.co.uk/vislog/2007/11/looping-through.html
Also, you might want to try look at the CreateSelection page method to narrow down your target shapes if you're dealing with a large number
I have a series of freeform shapes copied from a third party application.
These freeform shapes are made of open paths, which cannot be "combined" in PowerPoint (only freeforms made with closed paths can be combined).
The following macro goes through every shape selected, and if it is a freeform, it will create a copy with a closed path and then delete the original shape.
Sub close_poly()
Dim myshp As Shape
Dim mycol As String
Dim mynode As ShapeNode
Dim myxvals As Variant
Dim myyvals As Variant
Dim myxcol As String
Dim myycol As String
Dim myffb As FreeformBuilder
Dim mynewshp As Shape
Dim myname As String
For Each myshp In ActiveWindow.Selection.ShapeRange
With myshp
If .Type = msoFreeform Then
'################ set all line segments to straight
'(makes things easier in my specific case but will not work in many)
nodecount = 1
While nodecount <= .Nodes.Count
.Nodes.SetSegmentType nodecount, msoSegmentLine
nodecount = nodecount + 1
Wend
'############## collect coordinates
myxcol = ""
myycol = ""
For Each mynode In myshp.Nodes
myxcol = myxcol & mynode.Points(1, 1) & ","
myycol = myycol & mynode.Points(1, 2) & ","
Next
myxcol = Left(myxcol, Len(myxcol) - 1)
myycol = Left(myycol, Len(myycol) - 1)
myxvals = Split(myxcol, ",")
myyvals = Split(myycol, ",")
'##############create new freeform
Set myffb = ActiveWindow.View.Slide.Shapes.BuildFreeform(msoEditingAuto, myxvals(0), myyvals(0))
For i = 1 To UBound(myxvals)
myffb.AddNodes msoSegmentLine, msoEditingAuto, myxvals(i), myyvals(i)
Next i
myffb.AddNodes msoSegmentLine, msoEditingAuto, myxvals(0), myyvals(0)
Set mynewshp = myffb.ConvertToShape
myshp.PickUp
mynewshp.Apply
myname = myshp.Name
myshp.Delete
mynewshp.Name = myname
End If
End With
Next myshp
End Sub
Question: is there a simpler way to mimic the program's "close path" function in VBA?
Cheers