I have an excel workbook where the user imports text files into a "Data Importation Sheet". The number of files imported is dependent on how files the user wants to import. So far my workbook works great but I have hit one bump. When the user imports a file an identifier (i.e. 1, 2, 3, etc) gets assigned to that data set. Then the user selects an option from a dropdown box and calculations and plots will automatically be produced. The user also has the option to "Clear all data" where when this is selected all worksheets are cleared and if the user imports new files (after clicking the "clear all data" button) the identifier value restarts at 1. Here is my code for the identifier/counting how many files have been imported..
Public Sub Macro(Optional reset As Boolean = False)
Static i As Integer
If reset Then
i = -1
i = i + 1
Exit Sub
End If
i = i + 1
Worksheets("Hidden").Cells(i + 1, 1).FormulaR1C1 = "=" & i
Worksheets("Hidden").Cells(2, 2).FormulaR1C1 = "=" & i
End Sub
The problem I have ran into now is data will need to be imported into this sheet at a later date so when I save this file and reopen it then import more files the identifier/count for file imports restarts at 1 which I do not want to happen. I want to be able to just keep adding more files and have the code continue, I do not want to have to clear all the imported data and restart. Any ideas as to how I can do this? TIA.
I'd create a standalone function to manage the sequence. Store the value in a Workbook Name entry.
Note - if you had to manage multiple sequences you could promote the name of the sequence to a parameter instead of using a Constant within the Function.
Function NextSequence(Optional reset As Boolean = False)
Const COUNTER_NAME As String = "NM_COUNTER"
Dim nm As Name, i
On Error Resume Next
'is the name already created?
Set nm = ThisWorkbook.Names(COUNTER_NAME)
On Error GoTo 0
If nm Is Nothing Then
'not there yest - create it...
Set nm = ThisWorkbook.Names.Add(COUNTER_NAME, 0)
End If
If Not reset Then
i = Evaluate(nm.RefersTo)
i = i + 1
nm.RefersTo = i
Else
nm.RefersTo = 0
i = 0 '<< or 1 if you want NextSequence(True) to
' return the first sequence value
End If
NextSequence = i
End Function
Usage:
Public Sub Macro(Optional reset As Boolean = False)
Dim i
i = NextSequence(reset)
If reset Then Exit Sub
With Worksheets("Hidden")
.Cells(i + 1, 1).Value = i
.Cells(2, 2).Value = i
End With
End Sub
A quick fix for this would be to store the value of the identifier/count inside a cell and hide/lock the cell. The value inside the cell won't change upon restart yet you still can manipulate it inside VBA.
Very quick feel of how it should look like (probably innacurate as I don't have every info I need.)
Public Sub Macro(Optional reset As Boolean = False)
Static i As Integer
i = ActiveWorkBook.Sheets("Ressource").Range("A1").Value
If reset Then
i = -1
i = i + 1
Exit Sub
End If
i = i + 1
Worksheets("Hidden").Cells(i + 1, 1).FormulaR1C1 = "=" & i
Worksheets("Hidden").Cells(2, 2).FormulaR1C1 = "=" & i
End Sub
You could also create a CustomDocumentProperty to save the sequence number. You can pass a boolean to the method to reset:
Lastly, a helper function will check if the property exists, in order to be added if not.
Public Sub SequenceNumber(Optional ByVal Reset As Boolean = False)
If Not PropertyExists("Identifier") Then
ThisWorkbook.CustomDocumentProperties.Add Name:="Identifier", _
LinkToContent:=False, _
Type:=msoPropertyTypeNumber, _
Value:=0
End If
Dim p As Object
Set p = ThisWorkbook.CustomDocumentProperties("Identifier")
If Reset Then p.Value = 0 Else p.Value = p.Value + 1
End Sub
'Property Exists?
Private Function PropertyExists(ByVal propertyName As String) As Boolean
Dim p As Object
For Each p In ThisWorkbook.CustomDocumentProperties
If p.Name = propertyName Then
PropertyExists = True
Exit Function
End If
Next p
End Function
To call it:
SequenceNumber
SequenceNumber Reset:=True
Related
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 have a userform which contains a number of checkboxes from 1 to 100. I have written some very simple code so that when you submit the form it creates a binary string that represents the state of those 100 checkboxes, where 0 is false and 1 is true. The code to do this is here:
Private Sub BusRulesSubmit_Click()
Dim myBinaryString As String
Dim nm As String
Dim c As Control
For busRuleIdx = 1 To 100
nm = "CheckBox" & busRuleIdx
Set c = Controls(nm)
If c.Value = True Then
myBinaryString = myBinaryString & "1"
Else
myBinaryString = myBinaryString & "0"
End If
Next
msgBox myBinaryString
End Sub
I now want to open this Userform from another form, where I have a similar binary string, and use this string to set the values of the checkboxes to true or false as appropariate. However I am having issues when setting my control. The code is here:
Private Sub populateBusRules()
Dim c As Control
Dim myBRBinary As String
myBRBinary = "000000000011100000000000000000000000000000000000000000000000000000000010000000000000000000000000000"
For busRuleIdx = 1 To 100
nm = "BusinessRules.CheckBox" & busRuleIdx
Set c = Controls(nm)
If Mid(myBRBinary, buRuleIdx - 1, 1) = 1 Then
c.Value = True
Else
c.Value = False
End If
Next
End Sub
When I run the above, I get a runtime error "Could not find the specified object" and when going to debug it highlights this problem where the code states "Set c = Controls(nm)" - and I can see that it is failing in the first round of the loop i.e. where nm = "BusinessRules.CheckBox1"
Interestingly if I run the code "Set c = Controls(BusinessRules.CheckBox1)" I get no such issue.
Any help would be much appreciated.
Thanks,
Paul.
I think the BusinessRules is giving you the issue. In the Controls collection, there is no Control named "BusinessRules.CheckBox1", only one named "CheckBox1" within the BusinessRules.Controls collection. Assuming there aren't other issues mentioned in the comments above (like the form being closed before this is called), then this should fix your issue
I've got several check boxes to which I am going to change the visibility and caption of based on the index of a for loop. I have an array of 1 to X. Into my form I am passing along the array total and each array element is a string.
Anyway, on my worksheet I am passing:
Sub Stripdown_Button_Click()
LastUpdateColumn = Sheets("Update").UsedRange.Columns.Count
Header_Array = Range(Cells(7, 1), Cells(7, LastUpdateColumn)).Value
Header_Form.Header_Select LastUpdateColumn, Header_Array()
Header_Form.Show
End Sub
LastUpdateColumn will be an integer, Header_Array will be an array of strings.
My form, which I am probably completely screwing up at this point is as follows...
Public Sub Header_Select(Index As Integer, Header_List() As String)
For x = 1 To Index
If Header_List(1) <> "" Then
cb & Index.Visible = True
cb & Index.Caption = Header_List(Index)
Else
MsgBox "Form Error. Contact Engineering", vbOKOnly
On Error Resume Next
End Sub
You cannot create a variable name from a string; however the forms have a Controls default property accepting a control name as index
Dim cb As CheckBox
Set cb = Controls("cb" & Index)
cb.Visible = True
cb.Caption = Header_List(Index)
Since the property is the default property, this other syntax also works:
Set cb = Me("cb" & Index)
I need to set a parent Control to another control using the VBA code.
Actually i am looping to create differents controls dynamically and i want now to link them by child-parent.
Do someone has an idea ?
Here is the function where i create a new control and i set some values. And the last assignment is where i want to set the parent
Public Function apply_change(ihm_f, oNode, iMyName$, project$)
Dim new_elem
Dim oSubNodes As IXMLDOMNode
If oNode.Attributes.getNamedItem("Type").Text <> "Page" Then
If (oNode.Attributes.getNamedItem("Type").Text = "RefEdit") Then
Set new_elem = ihm_f.Designer.Controls.Add("RefEdit.Ctrl", oNode.nodeName, True)
Else
Set new_elem = ihm_f.Designer.Controls.Add("Forms." & oNode.Attributes.getNamedItem("Type").Text & ".1", oNode.nodeName, True)
End If
With new_elem
On Error Resume Next
.Width = oNode.Attributes.getNamedItem("Width").Text
.Top = oNode.Attributes.getNamedItem("Top").Text
.Left = oNode.Attributes.getNamedItem("Left").Text
.Height = oNode.Attributes.getNamedItem("Height").Text
Set .Parent = get_parent(oNode.ParentNode.nodeName, oNode, ihm_f)
End With
If oNode.Attributes.getNamedItem("Type").Text = "MultiPage" Then
Call new_elem.Pages.Remove(0)
Call new_elem.Pages.Remove(0)
For Each oSubNodes In oNode.ChildNodes()
Call new_elem.Pages.Add(oSubNodes.BaseName, oSubNodes.Attributes.getNamedItem("Caption").Text, oSubNodes.Attributes.getNamedItem("Index").Text)
Next oSubNodes
End If
End If
Set apply_change = ihm_f
End Function
The getparent function return a Controle which can be anything .. like textbox or combo box etc..
You provide so little information in your question that it is difficult to guess your objective.
However, I am guessing that you want to record that Control Xxxxx is the parent of control Yyyyy where the definition of “parent” has nothing to do with Excel’s definition of parent. I am further guessing you do not know how to access controls by number.
The macro below lists the name, type and top position of every control on a form by its index number within the collection Controls. Any property of a control is accessible in this way. If control Xxxxx is the parent of control Yyyyy, you can scan the collection to find their index numbers when the form loads and record this information for use when required.
Private Sub UserForm_Initialize()
Dim InxCtrl As Long
Dim LenNameMax As Long
Dim LenTypeMax As Long
LenNameMax = 0
For InxCtrl = 0 To Controls.Count - 1
If LenNameMax < Len(Controls(InxCtrl).Name) Then
LenNameMax = Len(Controls(InxCtrl).Name)
End If
If LenTypeMax < Len(TypeName(Controls(InxCtrl))) Then
LenTypeMax = Len(TypeName(Controls(InxCtrl)))
End If
Next
Debug.Print PadR("Name", LenNameMax) & "|" & PadR("Type", LenTypeMax) & "| Top"
For InxCtrl = 0 To Controls.Count - 1
Debug.Print PadR(Controls(InxCtrl).Name, LenNameMax) & "|" & _
PadR(TypeName(Controls(InxCtrl)), LenTypeMax) & "|" & _
PadL(Format(Controls(InxCtrl).Top, "#,###.00"), 8)
Next
End Sub
I need to reformat a XML file to .CSV.
I already opened the XML in Excel and did a little formating but now I really need to write a macro to get the data into shape. I already started bu I really have issues with the loop logic.
the List has a couple thousand Articles with a variable amount of subarticles.
each subarticle as a the same amount of properties but not every article has the same properties.
https://picload.org/image/ipialic/now.jpg
https://picload.org/image/ipialip/then.jpg
My Code up till now looks like this:
Option Explicit
Dim rowCount As Long, articleCount As Long, propertyCount As Integer, name As String
Sub Sortfunction()
rowCount = 1
articleCount = 0
propertyCount = 0
Do While Sheets("Test").Cells(rowCount, 1).Value <> "end"
If Cells(rowCount, 1).Value = "Reference" Then
rowCount = rowCount + 1
Do While Cells(rowCount, 3).Value = ""
If Cells(rowCount, 3).Value = "4" Then
End If
articleCount = articleCount + 1
Loop
articleCount = articleCount + 1
End If
rowCount = rowCount + 1
Loop
Sheets("result").Cells(1, 1).Value = rowCount
Sheets("result").Cells(2, 1).Value = articleCount
End Sub
At the end of the document i wrote the "end" to have a hook to stop the loop.
Can anyone provide some help? I'm really not the best programmer :-/
I'd really appreciate any help I can get :-)
here he's a translation into algorithm and some tips on functions
update: it was more tricky than I thought... I had to rewrite the code.
The main problem is "how to decide when change column".
I choose this solution "Each product in reference must have the same amount of properties".
If it's not the case, please indicate "how you decide when you have to create a new Column" (you can explain it in plain words)
Here the code rewrited. I tried it on your exemple, it work
Public Sub test()
' Set the range to navigate in your first sheet
Dim cell As Range: Set cell = Sheets("Feuil1").Range("A1")
' set the range to navigate in your result sheet
Dim res As Range: Set res = Nothing
' pos will be used to know the position of a product
Dim lastProperties As Range, posProperties As Range
' While the cell value is not "end"
Do While cell <> "end"
' if the cell is a reference
If cell = "Reference" Then
' Set the range of res
If res Is Nothing Then
Set res = Sheets("Feuil2").Range("A1")
Else
Set res = Sheets("Feuil2").Range("A" & lastProperties.offset(2).Row)
End If
' I set Offset(2) so you will have an empty line between 2 references
' Set the text of the new reference in the result
res = cell.offset(, 1) ' The reference is the cell 1 offset the right of the cell "Reference"
' WARNING : here no writing of titles anymore. It'll be done in the "Else".
' Here you just write "new reference" and reinit var
Else
' Here we have a property
' If the property alreay exist, consider it a new product in the reference
' When we are on a new property, the column of the product if the next to the right
If GetProperties(cell.offset(, 3), res, posProperties) Then
Set lastProperties = posProperties
End If
posProperties = cell.offset(, 4)
End If
' BIG FORGET: you have to get the next cell
Set cell = cell.offset(1)
Loop
End Sub
And the function to search / create your properties
Private Function GetProperties(ByVal propValues As String, ByVal start As Range, ByRef position As Range) As Boolean
Set position = start.offset(1)
' Is the cell below the properties ? Return the row below
' Search for the first "empty row" on the line
If position = propValues Then
Do
Set position = position.offset(, 1)
Loop While Trim(position) <> ""
' Indicate it's an existing value
GetProperties = True
Exit Function
End If
' Is the range empty ?
If Trim(position) = "" Then
' Create the new properties
position = propValues
Set position = position.offset(, 1)
GetProperties = False
Exit Function
End If
' Search the properties in the row below
GetProperties = GetProperties(propValues, position, position)
End Function
It should do the work. If you have any question on understanding some part, don't hesitate
if you don't know about Offset, some reading : https://msdn.microsoft.com/en-us/library/office/ff840060.aspx