I've got a Product in CATIA containing several CATParts.
I use the symbol Sectioning in DMU Review Creation to create a section, to cut the product.
This section is called Section.1.
What I'm looking for is a code to take the name from CATPart 1 ( myPartNumber1) and change the name of the section from "section.1" into myPartNumber1.
This is my code so far in vb.NET:
Sub x()
Set productDocument1 = CATIA.ActiveDocument
myPartNumber1 = productNumber1.Product.Products.Item(1).Name
Set selection1 = productDocument1.Selection
selection1.Search("Name='Section.1',all")
selection1.item(1).value.Name = myPartNumber1
End Sub
I get a problem in the last line.
Sub CATMain()
Set oprod = CATIA.ActiveDocument.Product
Set TheSections = oprod.GetTechnologicalObject("Sections")
Set mySection = CATIA.ActiveDocument.Product.GetTechnologicalObject("Sections")
Set oSection = oprod.GetTechnologicalObject("Sections")
Set selectionpart = CATIA.ActiveDocument.selection
partcount = selectionpart.Count
for k = 1 to partcount
Set selectionpart = oprod.Products.Item(k)
myPartNumber = CATIA.ActiveDocument.Product.Products.Item(k).Name
sectioncount = oSection.Count
MsgBox sectioncount
for i = 1 To sectioncount
Set oSection = mySection.item(i)
oSection.Name = myPartnumber
Next
Next
End Sub
PROBLEM:
What I get is that all of my Sections get the name of the first Part in Product
What I need ist: first section gets the name of the first PArt, second sections gets the name of the second Part ...
I've obviously written something wrong in my loops.
THX
Related
I have a document with a text in a table of two columns, and i want to make a macro that equals two paragraphs in both columns.
I'm doing this thru checking the location of first character in each paragraph relative to page using range.information(wdVerticalPositionRelativeToPage), and then comparing it to the same paragraph in the other column and adding the difference to the Paragraphs.SpaceBefore of the upper paragraph.
my problem is: that it's not doing it exactly, it's still not having a small gap between the paragraphs in both columns.
is there any way to make this process a little more exact?
here is my macro:
Sub EqualColumns()
Dim EnRange As Range, EnCh As Range
Dim YiRange As Range, YiCh As Range
Dim PaCount As Long
Set YiRange = Selection.Tables(1).Columns(1).Cells(2).Range
Set EnRange = Selection.Tables(1).Columns(2).Cells(2).Range
' paregraphes
set pacount = EnRange.Paragraphs.Count
For MyLoop = 1 To pacount
Set EnPa = EnRange.Paragraphs(MyLoop).Range
Set EnCh = EnPa.Characters(1)
EnPo = EnCh.Information(wdVerticalPositionRelativeToPage)
Set YiPa = YiRange.Paragraphs(MyLoop).Range
Set YiCh = YiPa.Characters(1)
YiPo = YiCh.Information(wdVerticalPositionRelativeToPage)
If EnPo > YiPo Then
MyAm = EnPo - YiPo
YiRange.Paragraphs(MyLoop).SpaceBefore = YiRange.Paragraphs(MyLoop).SpaceBefore + MyAm
ElseIf EnPo < YiPo Then
MyAm = YiPo - EnPo
EnRange.Paragraphs(MyLoop).SpaceBefore = YiRange.Paragraphs(MyLoop).SpaceBefore + MyAm
End If
Next
End Sub
I'm using UFT (vbscript) to automate a process between SAP and a Web page. Using SAP transaction S_ALR_87013534, I have a piece of code in UFT that will expand the tree completely and extract the value associated with one of the order numbers:
set tree = SAPGuiSession("Session").SAPGuiWindow("Execute Drilldown Report").SAPGuiTree("TableTreeControl")
tree.OpenItemContextMenu "PRJ "&projNum,"PRJ "&projNum
tree.SelectMenuItemById "&EXPAND"
tree.SelectNode "PRJ "&projNum
colKey_plan1 = getColNameFromTitle(tree, "Plan 2--Overall")
rowContainingOrdNum = findBudget(tree, ordNum)
plannedProjectBudget = tree.Object.GetItemText(tree.Object.GetAllNodeKeys(rowContainingOrdNum(0)), colKey_plan1)
Function getColNameFromTitle(tree, title)
set colNames = tree.Object.GetColumnNames
For i = 1 To (colNames.length-1)
selectedColTitle = tree.Object.GetColumnTitleFromName(colNames(i))
If selectedColTitle = title Then
getColNameFromTitle = colNames(i)
Exit For
End If
Next
End Function
Function findBudget(tree, ordNum)
rowContainingOrdNum = Array()
Set columnNames = tree.Object.GetColumnNames()
set columnKeys = tree.Object.GetColumnCol(columnNames(0))
For i = 1 To (columnKeys.length-1)
If InStr(columnKeys(i), ordNum)>0 Then
AddItem rowContainingOrdNum, i
Exit For
End If
Next
findBudget = rowContainingOrdNum
End Function
Function AddItem(arr, val)
ReDim Preserve arr(UBound(arr) + 1)
arr(UBound(arr)) = val
AddItem = arr
End Function
This works perfectly, but when I use a different report, S_ALR_87013543, it's still recognised as a tree but the above code doesn't work as there is no EXPAND option at the Object heading. I'm not very familiar with SAP and all their trees and how to use automation with it, so any guidance or tips are appreciated.
Left is the report I need to expand, and right is the report the code works with:
Solution:
Set TreeObj = SAPGuiSession("Session").SAPGuiWindow("Actual/Plan/Variance").SAPGuiTree("TableTreeControl").Object
Set AllValues = TreeObj.GetAllNodeKeys
Count = AllValues.Count
Found = 0
For i = 0 to Count-1
NodeText = TreeObj.GetNodeTextByKey(AllValues(i))
If NodeText = WBSelement Then
Found = 1
Exit For
End if
Next
If Found = 1 Then
SAPGuiSession("Session").SAPGuiWindow("Actual/Plan/Variance").SAPGuiTree("TableTreeControl").SelectNode WBS
End If
Catia V5 R24
1) is there any way to check by the VBA code if the parameter in catia is locked ?
2) Is there any way to check by the VBA code if the value of the parameter is set from the KWA rule ?
What I'm going to do:
I will have a Catia Part with necessary geometry, parameters and rules in KWA.
I will add only in VBA window where user can easily edit and modify a geometry.
Below You can find a sample How it will looks like
User Will chose a method for the calculation parameter (3 and 4)
if he will chose 1st (script will check if the parameter in PRT file has a lock status, and if it is set from the KWA Rule) if yes than script should change a window option (Enabled > False, disable a posililiby to put any values to this window), and Enable button 2
I know that there will be more problems with this window, but I will try to solve them one by one.
Here is my test code
Private Sub cmdClose_Click()
Call ChangeValue("Show_Window", "No")
Me.Hide
'End
End Sub
Public Sub Start_Click()
On Error Resume Next
Set curDoc = CATIA.ActiveDocument
Set mySel = curDoc.Selection
mySel.Search "Name= 'xy plane', in"
If TypeName(curDoc) = "PartDocument" Then Set curPrt = curDoc.Part
If TypeName(curDoc) = "ProductDocument" Then Set curPrt = mySel.FindObject("CATIAPart")
Set ihybBodies = curPrt.HybridBodies
Set ihybBody = curPrt.InWorkObject
Dim iPars As Parameters: Set iPars = curPrt.Parameters
Dim iPar As Parameter
'search parameters length
mySel.Clear: mySel.Add ihybBody: mySel.Search "Name=Length_Param,in"
Set iPar = mySel.Item2(1).Value: LengthParam = iPar.Value & " mm"
'search parameters length 2nd method
Set iPar = Parameters.Item("Length_Param").Value: Length2ndMethod = iPar.Value & " mm"
'check lock status
Dim myLockStatus As Boolean
myLockStatus = Parameters.LockStatus("Length_Param").Lock
MsgBox myLockStatus
'---------------------------------------------------------------------------------------------------------
'search string
mySel.Clear: mySel.Add ihybBody: mySel.Search "Name=String Param,in"
Set iPar = mySel.Item2(1).Value: StringParam = iPar.Value
'---------------------------------------------------------------------------------------------------------
'search ListBox
mySel.Clear: mySel.Add ihybBody: mySel.Search "Name=String_List,in"
Set iPar = mySel.Item2(1).Value
'Clear List
ListBox.Clear
'Add Items to list from CADPRT
cnt = iPar.GetEnumerateValuesSize
Dim ParamValues() As Variant
ReDim ParamValues(cnt)
iPar.GetEnumerateValues ParamValues
For i = 0 To cnt - 1
With ListBox
.AddItem ParamValues(i)
End With
Next
'set value from PRT
ListBox = iPar.Value
'---------------------------------------------------------------------------------------------------------
End Sub
I need to export the Catia Spec tree to use as a BoM.
The Export Should:
Go to Excel and will use the WalkDownTree function.
Have the PartNumber, Nomenclature and a User Added
Property called "Sinex Ref".
It will also have to make sure that the Exported Tree ignores Parts
and Products called "Ref".
Present the Quantity of each item using the
PartNumber.
Include the deactivated parts but mention that they
are deactivated.
I'm new to Catia and VBA and have come up with the following (I made adjustments to other macros that i have found but noticed that they ignore the children in the Tree). Currently the macro generates the Excel file and in the same cell cycles through all of the parts and children in the spec tree, regardless if they're deactivated or not.
Sub CATMain()
' ********* is the current document a CATIA Product **************
If CATIA.Documents.Count = 0 Then
MsgBox "There are no CATIA documents open. Please open a CATIA document and try again.", ,msgboxtext
Exit Sub
End If
If InStr(CATIA.ActiveDocument.Name, ".CATProduct") < 1 Then
MsgBox "The active document is not a Product. Please open a CATIA Product and try again.", ,msgboxtext
Exit Sub
End If
' ************* General declarations for the Active CATIA session *****************
Dim oProdDoc As ProductDocument
t = 1
Set oProdDoc = CATIA.ActiveDocument
Dim oRootProd As Product
Set oRootProd = oProdDoc.Product
Dim par As Parameters
Set par = oRootProd.UserRefProperties
Dim SinexRef As String
' *************** begin spec tree scroll ******************
Call WalkDownTree(oRootProd)
End Sub
Sub WalkDownTree(oInProduct As Product)
Dim oInstances As Products
Set oInstances = oInProduct.Products
On Error Resume Next
Set Excel = GetObject(, "EXCEL.Application")
If Err.Number <> 0 Then
Set Excel = CreateObject("EXCEL.Application")
Excel.Visible = True
Excel.Workbooks.Add
End If
If t <> 1 Then
for i=1 to oInProduct.Count
'**************************** Export title ***************************
row=2
col=1
Excel.Columns.Columns(1).Columnwidth = 5
Excel.Columns.Columns(2).Columnwidth = 15
Excel.Cells(row,col+1).Value = "CATProduct:"
Excel.Cells(row,col+1).Font.Bold = true
Excel.Cells(row,col+1).HorizontalAlignment = 3
Excel.Cells(row,col+2).Value = CATIA.ActiveDocument.Name
' **************************** Export column titles ***************
row=4
Excel.Cells(row,col+1).Value = "Instance Name"
Excel.Cells(row,col+1).Font.Bold = true
Excel.Columns.Columns(2).Columnwidth = 20
Excel.Cells(row,col+1).borders.LineStyle = 1
Excel.Cells(row,col+1).HorizontalAlignment = 3
Excel.Cells(row+2,col+1).Value = oInProduct.ReferenceProduct.PartNumber
Excel.Cells(row,col+2).Value = "Ref"
Excel.Cells(row,col+2).Font.Bold = true
Excel.Columns.Columns(3).Columnwidth = 15
Excel.Cells(row,col+2).borders.LineStyle = 1
Excel.Cells(row,col+2).HorizontalAlignment = 3
Excel.Cells(row+2,col+2).Value = oInProduct.ReferenceProduct.Nomenclature
Excel.Cells(row,col+3).Value = "Quantity"
Excel.Cells(row,col+3).Font.Bold = true
Excel.Columns.Columns(4).Columnwidth = 15
Excel.Cells(row,col+3).borders.LineStyle = 1
Excel.Cells(row,col+3).HorizontalAlignment = 3
Excel.Cells(row+2,col+3).Value = 1 'insert item quantity corresponding to PartNumber
Excel.Cells(row,col+4).Value = "SinexRef"
Excel.Cells(row,col+4).Font.Bold = true
Excel.Columns.Columns(5).Columnwidth = 15
Excel.Cells(row,col+4).borders.LineStyle = 1
Excel.Cells(row,col+4).HorizontalAlignment = 3
Excel.Cells(row+2,col+4).Value = 1 'insert Sinex Ref corresponding to PartNumber
t = t + 1
Next
End If
Dim k As Integer
For k = 1 To oInstances.Count
Dim oInst As Product
Set oInst = oInstances.Item(k)
Call WalkDownTree(oInst)
Next
End Sub
Assuming by
in the same cell cycles through all of the parts and children in the spec tree
you mean that it is writing/overwriting data from CATIA in the same cell, that is because you aren't incrementing anything regarding Excel rows/columns.
I personally would create headers for things like CATProduct, Instance Name, etc. then put pure data below instead of repeating these identical headers every single time, but your format will work as well, it might just be more difficult to summarize data in Excel.
Anyway, to maintain your existing format, you need to increment your Row at the end of your loop, around where t is incremented.
In the existing loop, it appears that rows 2-6 are used (5 rows total) for the first oInProduct. There is a row = 2 at the beginning of the loop which needs to be put just before the loop, this means it will start from the second row. There is also a row = 4 inside the loop which needs to be changed, we can use row = row + 2 to get the same effect. Then, at the end of the loop, we increment again to reach that total of 5, so use row = row + 3.
row = 2
for i = 1 to oInProduct.Count
'**************************** Export title ***************************
col=1
Excel.Columns.Columns(1).Columnwidth = 5
...
row = row + 2 'previously row = 4
...
Excel.Cells(row,col + 4).HorizontalAlignment = 3
Excel.Cells(row + 2,col + 4).Value = 1 'insert Sinex Ref corresponding to PartNumber
t = t + 1
row = row + 3
Next
Try
-->Analyze-->Bill of Material-->Define Format (for optional options)-->>Save as-->File format as .xls
Or:
-->File--> Save As --> Filetype:txt...Sure it's txt but maybe you can convert to .xls
(expecially if you have missing licenses)
I have used AssemblyConverter object which is available in Catia libraries to extract BOM.I found this when I recorded macro using the steps mentioned in above comment.
Try -->Analyze-->Bill of Material-->Define Format (for optional options)-->>Save as-->File format as .xls
I think this is the simplest and fast. Also, we can change format and location of file too.
Recorded Macro:
Sub CATMain()
Dim productDocument1 As ProductDocument
Set productDocument1 = CATIA.ActiveDocument
Dim product1 As Product
Set product1 = productDocument1.Product
Dim assemblyConvertor1 As AssemblyConvertor
Set assemblyConvertor1 = product1.GetItem("BillOfMaterial")
Dim arrayOfVariantOfBSTR1(4)
arrayOfVariantOfBSTR1(0) = "Quantity"
arrayOfVariantOfBSTR1(1) = "Part Number"
arrayOfVariantOfBSTR1(2) = "Type"
arrayOfVariantOfBSTR1(3) = "Nomenclature"
arrayOfVariantOfBSTR1(4) = "Revision"
Set assemblyConvertor1Variant = assemblyConvertor1
assemblyConvertor1Variant.SetCurrentFormat arrayOfVariantOfBSTR1
Dim arrayOfVariantOfBSTR2(1)
arrayOfVariantOfBSTR2(0) = "Quantity"
arrayOfVariantOfBSTR2(1) = "Part Number"
Set assemblyConvertor1Variant = assemblyConvertor1
assemblyConvertor1Variant.SetSecondaryFormat arrayOfVariantOfBSTR2
assemblyConvertor1.[Print] "XLS", "C:\Users\Desktop\BOM.xls", product1
End Sub
I have a VBA macro that uses Microsoft MapPoint to calculate the distance between two locations for each record in my spreadsheet. I have about 120,000 records to process. The program runs smoothly for about 10,000 iterations then returns a Type Mismatch error where I define the MapPoint locations in my error handler. At which point, I select 'Debug' and then resume execution without editing any code, and it will run successfully for another 10,000 or so records before the same thing happens again.
I've checked my data, and I can't see why there would be a type mismatch, or for that matter why the code would choke on a record one time, and then, without resetting anything, handle the same record upon resuming. Any idea why this would happen?
For reference,
- column M contains locations of the form "X County, ST"
- column AN contains a separate location as ZIP
- column G contains the same location data as AN but in the form "X County, ST"
Sub distance_from_res()
Dim oApp As MapPoint.Application
Dim k As Long
Dim count As Long
Dim errors As Long
k = 0
count = Sheets("i1_20041").Range("A2", Sheets("i1_20041").Range("A2").End(xlDown)).count
errors = 0
Set oApp = CreateObject("MapPoint.Application.NA.11")
oApp.Visible = False
Set objMap = oApp.NewMap
Dim objRes As MapPoint.Location
Dim objFish As MapPoint.Location
'Error executes code at 'LocError' and then returns to point of error.
On Error GoTo LocError
Do While k < count
If Sheets("i1_20041").Range("M2").Offset(k, 0) <> "" Then
'Sets MapPoint locations as [County],[State] from Excel sheet columns "INT_CNTY_ST" and "ZIP".
Set objRes = objMap.FindResults(Sheets("i1_20041").Range("AN2").Offset(k, 0)).Item(1)
Set objFish = objMap.FindResults(Sheets("i1_20041").Range("M2").Offset(k, 0)).Item(1)
'Calculates distance between two locations and prints it in appropriate cell in Column AO.
Sheets("i1_20041").Range("AO2").Offset(k, 0) = objRes.DistanceTo(objFish)
Else
errors = errors + 1
End If
k = k + 1
Loop
'Displays appropriate message at termination of program.
If errors = 0 Then
MsgBox ("All distance calculations were successful!")
Else
MsgBox ("Complete! Distance could not be calculated for " & errors & " of " & count & " records.")
End If
Exit Sub
LocError:
If Sheets("i1_20041").Range("G2").Offset(k, 0) = "" Then
errors = errors + 1
Else
'THIS IS WHERE THE ERROR OCCURS!
Set objRes = objMap.FindResults(Sheets("i1_20041").Range("G2").Offset(k, 0)).Item(1)
Set objFish = objMap.FindResults(Sheets("i1_20041").Range("M2").Offset(k, 0)).Item(1)
'Calculates distance between two locations and prints it in appropriate cell in Column AO.
Sheets("i1_20041").Range("AO2").Offset(k, 0) = objRes.DistanceTo(objFish)
End If
k = k + 1
Resume
End Sub
UPDATE:
I incorporated most of the suggestions from #winwaed and #Mike D, and my code is now more accurate and doesn't choke on errors. However, the old problem reared its head in a new form. Now, after around 10,000 iterations, the code continues but prints the distance of the ~10,000th record for every record afterwards. I can restart the code at the trouble point, and it will find the distances normally for those records. Why would this happen? I've posted my updated code below.
Sub distance_from_res()
Dim oApp As MapPoint.Application
Dim k As Long
Dim rc As Long
Dim errors As Long
Dim dist As Double
Dim zipRes As Range
Dim coRes As Range
Dim coInt As Range
Dim distR As Range
Set zipRes = Sheets("Sheet1").Range("C2")
Set coRes = Sheets("Sheet1").Range("B2")
Set coInt = Sheets("Sheet1").Range("E2")
Set distR = Sheets("Sheet1").Range("G2")
k = 0
rc = Sheets("Sheet1").Range("F2", Sheets("Sheet1").Range("F2").End(xlDown)).Count
errors = 0
'Start MapPoint application.
Set oApp = CreateObject("MapPoint.Application.NA.11")
oApp.Visible = False
Set objMap = oApp.NewMap
Dim objResultsRes As MapPoint.FindResults
Dim objResultsInt As MapPoint.FindResults
Dim objRes As MapPoint.Location
Dim objInt As MapPoint.Location
Do While k < rc
'Check results for Res Zip Code. If good, set first result to objRes. If not, check results for Res County,ST. If good, set first result to objRes. Else, set objRes to Nothing.
Set objResultsRes = objMap.FindResults(zipRes.Offset(k, 0))
If objResultsRes.ResultsQuality = geoFirstResultGood Then
Set objRes = objResultsRes.Item(1)
Else
Set objResultsRes = Nothing
Set objResultsRes = objMap.FindResults(coRes.Offset(k, 0))
If objResultsRes.ResultsQuality = geoFirstResultGood Then
Set objRes = objResultsRes.Item(1)
Else
If objResultsRes.ResultsQuality = geoAmbiguousResults Then
Set objRes = objResultsRes.Item(1)
Else
Set objRes = Nothing
End If
End If
End If
Set objResultsInt = objMap.FindResults(coInt.Offset(k, 0))
If objResultsInt.ResultsQuality = geoFirstResultGood Then
Set objInt = objResultsInt.Item(1)
Else
If objResultsInt.ResultsQuality = geoAmbiguousResults Then
Set objInt = objResultsInt.Item(1)
Else
Set objInt = Nothing
End If
End If
On Error GoTo ErrDist
distR.Offset(k, 0) = objRes.DistanceTo(objInt)
k = k + 1
Loop
Exit Sub
ErrDist:
errors = errors + 1
Resume Next
End Sub
You are constructing a somewhat complex range object (Range -> Offset -> Item). DIM temporary range objects and do it in steps so you can see where exactly the problem occurs
tmpR1 = Sheets("i1_20041").Range("G2")
tmpR2 = tmpR1.Offset(k,0)
then examine the .Count property of the .FindResult before you try accessing Item(1) .... maybe this item doesn't exist ?!?
Debug.Print objMap.FindResult(tmpR2).Count
Hint:
looking at your code, I observe that you use a variable "count". This variable name overlaps with the "Count" property in your second line of code - that's why the "Count" keyword at the end of the statement is printed all lowercase. It's not got anything to do with the errors (we pretend ;-) ), but bad style anyway.
MikeD is right with your dangerous FindResults() calls. However, there is a better way to check the results. The "FindResults collection" isn't a pure collection but includes an extra properties called "ResultsQuality". Docs are here:
http://msdn.microsoft.com/en-us/library/aa493061.aspx
Resultsquality returns a GeoFindResultsQuality enumeration. You want to check for the values geoAllResultsGood and geFirstResultGood. All other results should give an error of some result. Note that your existing code would work find with (for example) Ambiguous Results, even though it is unlikely the first result is the correct one. Also it might match on State or Zipcode (because that is the best it can find) whcih give you an erroneous result. Using ResultsQuality, you can detect this.
I would still check the value of Count as an additional check.
Note that your code is calculating straight line (Great Circle) distances. As such the bottleneck will be the geocoding (FindResults). If you are using the same locations a lot, then a caching mechanism could greatly speed things up.
If you want to calculate driving distances, then there are a number of products on the market for this (yes I wrote two of them!).