How to use String value as a dot operation in VBA? it is possible? - excel

Sub getTrailInfo()
Dim attr As Variant
Dim attrTB As String
attrNames = Split("trailName,trailType,aSideSite,zSideSite,status", ",")
Dim trailForm As New formTrailInfo
For Each attr In attrNames
attrTB = attr + "TB"
trailForm.attrTB = attr
Next attr
trailForm.Show
End Sub
When I run the above code it gives a compilor error: Method or Data not found at line trailForm.attrTB = attr
I have required variables in attrNames String array. I need to put values of these variables in corosponding textboxes in a userForm. The name of Text Box in this userForm is attrNameTB. For example Text box for trailName is trailNameTB.

You cannot use VBA like that.
When you start your code, the compiler will first compile the code and check that you want to access a property named attrTB of your form. This doesn't exist and you will get the error you mentioned.
The compiler cannot wait until your variable attrTB has an actual value and then guess that you don't want a property with that name, but use the content of that variable as property name.
However, every form has a collection of all it's controls (button, edit boxes, combo boxes, labels...), and you can access the members of a collection either by index or by name. As you have the name of the control in attrTB, you could simply write
trailForm.Controls(attrTB).Text = attr

Related

How can I use cell value in declaration of new class object?

I have a fairly simple question to which I can't seem to find the answer anywhere so I'll try here. I have created a new class called "Groups" in vba. What I want to do is retrieve a value from a cell in excel and use this as the name of the new group I want to create. I've tried accessing the value through Range("B20").Value but then I need to store it in another variable first and if I do that I can't use it as the name after since it thinks I want the group to be named like my variable I stored it in.
Does anyone know a way around this? Appreciate any help or suggestions.
Below is what I've tried which doesn't work.
Dim Range("B20").Value As Group
I've also tried this but then it thinks I want to name the group as my variable "getName"
Dim getName As String
getName = Range("B20").Value
Dim getNAme As Group
Kind regards,
Jahlove
As others have suggested in the comments, you cannot change a string variable into a variable name. However, if all you want to access/reference an object using a string, you can try a Scripting.Dictionary (docs here) like this:
Sub DynamicGroupNaming()
Dim sGroupName As String
Dim dictGroups As Object
Set dictGroups = CreateObject("Scripting.Dictionary")
'Change Sheet1 to the name of your worksheet
sGroupName = ThisWorkbook.Sheets("Sheet1").Range("B20").Value
' Add a new group to the dictionary
dictGroups.Add sGroupName, New Group
' Access the group's properties/methods in the usual way
dictGroups(sGroupName).Name = sGroupName
MsgBox dictGroups(sGroupName).Name
Set dictGroups = Nothing
End Sub

MS Access: Choosing Worksheet from Excel Workbook

I'm writing some code in MS Access and I reached to the point where user needs to choose on which worksheet of an Excel workbook there need to be performed some operation. I don't know, what name of this worksheet is or on which position it is placed.
I was thinking about a solution which will show user a form (as modal form) with listbox containing all sheets names'. When user click one of them form will show aside A1:J10 range (so user can choose the right one worksheet). After confirming choosen worksheet it will return as worksheet object.
Every thing was great untill I wanted to pass a object variable to the form. In openArgs I can only pass a string. I was even thinking about a class which will open this form but it's still no luck with passing object parameter.
I'm trying to avoid global/public variables.
Any ideas?
Assuming your object is wsObj, can't you just use wsObj.Name ?
Also have a look at wsObj.CodeName, which may be interesting as well.
There are many possibilities to send some value between objects.
A) Using Global vars into ACCESS Vba module
Global yourvariable As String
if you need some different value can use Variant, Single, etc.
B) Using Windows Register
To save value:
SaveSetting "yourprojectname", "Settings", "yourvariable", yourvalue
To retrieve value:
retvalue = GetSetting("yourprojectname", "Settings", "yourvariable", "your_default_value_if_not_exist")
C) Using OpenArg into Open Form command procedure
DoCmd.OpenForm "stDocName", acNormal, "filter_if_needed", "stlinkcriteria", acFormEdit, acWindowNormal, "arguments_forOpenArgs"
On destination form
Private Sub Form_Open(cancel as integer)
your_args=Me.OpenArgs
On all three possible solutions you can send more than one value using a chain with vars and values, an example:
myvar_mutiple="name=John Doe|address=Rua del Percebe 34|location=Madrid|phone=34 91 1234567"
On this example i used "pipe" (AltGr on key 1) char to separate each var=value
Then on destination procedure only need split each pair:
splitvar=Split(myvar_multiple,"|")
With this you obtain for each "splitvar" an element like "name=John Doe"
Do again an split with "=" to obtain variable an value. For each value you can reassign the result to a local vars.
Full code example:
if me.OpenArgs<>"" then
splitvar=Split(me.OpenArgs,"|")
for x=0 to ubound(splitvar)
tmpsplit=Split(splitvar(x),"=")
paramvars=tmpsplit(0)
paramvalue=tmpsplit(1)
select case paramvars
case "name"
stname=paramvalue
case "address"
straddress=paramvalue
case "location"
strlocation=paramvalue
case "phone"
strphone=paramvalue
end select
next
end if
Some recommendations that i use for this code "multiple vars":
- always use Low Case variable or change this:
paramvars=tmpsplit(0)
by
paramvars=lcase(tmpsplit(0))
-if you need to use "=" into value you can change by other alternative char or search the first "=" form left (i used this solution instead Split)
paramvars=trim(lcase(left(splitvar(x),len(splitvar(x))-(len(splitvar(x))-instr(splitvar(x),"="))-1)))
remember that you can send any value and can be converted on destination code. On this sample i use only String so you can use cLng or cInt etc.
Over your solution to select Sheet on excel from Access i think there are better alternatives.
IN the forms Module you can declare a property as object and then set that property once loaded. So in the form module
Option Explicit
Private myObj as object
Property Set DesiredWorksheet(o as object)
set myobj = o
End
and then in your code
Load myform
set myform.desiredworksheet = wsObj
myform.show
Ahh, sorry I was writing Excel not Access!!!
Docmd.openform f
f.desiredworksheet = ws.obj
docmd.openform f, windowmode:=acdialog
ought to work

VBA Customize collection object

I've been trying to learn how to create customized collections in Excel VBA and I found this piece of code on MSDN. While I understand most of it, can anyone tell me what the last code Set Add = empNew is doing? I don't understand it's comment. Thank you!
' Methods of the Employees collection class.
Public Function Add(ByVal Name As String, _
ByVal Salary As Double) As Employee
Dim empNew As New Employee
Static intEmpNum As Integer
' Using With makes your code faster and more
' concise (.ID vs. empNew.ID).
With empNew
' Generate a unique ID for the new employee.
intEmpNum = intEmpNum + 1
.ID = "E" & Format$(intEmpNum, "00000")
.Name = Name
.Salary = Salary
' Add the Employee object reference to the
' collection, using the ID property as the key.
mcolEmployees.Add empNew, .ID
End With
' Return a reference to the new Employee.
Set Add = empNew
End Function
You will notice that Add is the name of the Function. By issuing Set Add = newEmp your code is declaring that the return value (or object, in this case) of the function, is the newly created employee object newEmp. This means that the function will pass the variable newEmp back to its caller.
Say that you had some procedure calling your function, you would be able to do this:
Sub listEmployees
Dim e As Employee
' Create a new employee, and assign the variable e to point to this object
Set e = Add("John", 1000) ' Notice that the only reason we use "add" here is because it is the name of the function you provided
' e is now an Employee object, after being created in the line above, meaning we can access whatever properties is defined for it. The function Add lists some properties, so we can use those as examples.
Debug.Print e.Name
Debug.Print e.Salary
Debug.Print e.ID
End Sub
First, you need to define the new Type you have created, so put the following code on top of your module:
Public Type Employee
id As String
Name As String
Salary As Long
End Type
Then, inside your Public Function Add , change to Dim empNew As Employee.
Not sure why you need the following line : mcolEmployees.Add empNew, .id ??
and the last line modify to Add = empNew.
Then, when I test this Function from the following Sub:
Sub testEmp()
Dim s As Employee
s = Add("Shai", 50000)
End Sub
I get for s in the immediate window the following values:
s.id = E00001
s.Name = "Shai"
s.Salary = 50000
I hope this is what you intended in your post.

Extracting the Company property from a Word document using Excel VBA

I'm using Excel 2010 and VBA to reorganize some Word documents on my C:\ drive and I want to pull the "Company" property of each document into a sheet containing a list of documents. The full file path of each document appears in row A (like so: "C:\folder\subfolder\file.doc"),and I would like to populate the corresponding "Company" property in row F.
I'm trying to write a macro for a custom Excel function DocCompany that will use a text string containing a local filepath to return the "Company" property of the document that the filepath identifies.
I've had better luck with the Last Modified and File Size properties, as both have dedicated VBA functions (FILEDATETIME and FILELEN, respectively). In each case, all I had to do was write a macro for a custom Excel function that returns the result of the VBA function for a file path string located in the sheet.
Given the following function, =GetFileDateTime(A1) will return the last save date for the document identified by the filepath string contained in A1.
Function GetFileDateTime(FileName As String) As Date
GetFileDateTime = FileDateTime(FileName)
End Function
Given the following function, =FileSize(A1) will return the file size in bytes of the document identified by the filepath string contained in A1.
Function FileSize(FileName As String)
FileSize = FileLen(FileName)
End Function
However, the Company property has no corresponding VBA function, so (as I said above), I want to write a macro defining a custom Excel function DocCompany that will accept a local filepath string as input and use it to output the Company property of the document.
This is what my macro looks like right now:
Function CompanyID(FileName As String) As String
CompanyID = Documents(FileName).Open
Documents(FileName).BuiltinDocumentProperties (wdPropertyCompany)
End Function
When I try to save it, Excel returns the error message "Compile error: Sub or Function not defined". Then it selects the reference to the "Documents" collection in the second row.
Why does Excel insist that I define "Documents" as a variable when every reference I can find confirms that it IS in fact an object or collection? What can I do to make this code work? Do I need to take a different approach?
Why does Excel insist that I define "Documents" as a variable when every reference I can find confirms that it IS in fact an object or collection?
Since Documents is not part of the Excel object model, it is being interpreted as a variable. You need to bind Word to the Excel instance, and reference that instance of the Word Application class.
Function CompanyID(FileName As String) As String
Dim wdApp as Object 'WOrd.Application
Dim doc as Object 'Word.Document
Const wdPropertyCompany as Long = 21 'Explicit reference for late-bound Word Application
Set wdApp = CreateObject("Word.Application")
Set doc = wdApp.Documents.Open(FileName)
CompanyID = doc.BuiltinDocumentProperties (wdPropertyCompany)
doc.Close False
End Function
Function F_snb(c00)
With GetObject(c00)
F_snb = .BuiltinDocumentProperties(21)
.Close 0
End With
End Function
in A2: G:\OF\example.docx
in D2: =F_snb(A2)

Using multiple values field in Lotus Notes

I am trying to write a logging system for a form in Lotus Notes but I am at the part where I am not sure how I can append the information about the fields that are changed in the log fields. There are 3 fields that I use Log_Date (date), Log_User and Log_Actions (Text, allow multiple values).
I thought if I add comma to the log field it will create a new line when displaying the form but I am still getting a type mismatch on the case 2 line.
How can I append the new values to the log fields?
Sub Querysave(Source As Notesuidocument, Continue As Variant)
' Compare the values in the form after it is saved with its original values when the document is not a new document.
Dim doc As NotesDocument
Set doc = Source.Document
Dim session As New NotesSession
Dim user As String
user = session.CommonUserName
If newDoc Then
doc.Log_Date = Now()
doc.Log_User = user
doc.Log_Actions = "New document created."
Else
' Load fields value to the array
lastValues(0) = doc.QCR_No(0)
lastValues(1) = doc.QCR_Mobile_Item_No(0)
lastValues(2) = doc.QCR_Qty(0)
' Compared each value in the array to see if there is any difference
Dim i As Integer
For i = 0 To 2
If lastValues(i) <> originalValues(i) Then
Select Case i
Case 2 : doc.Log_Actions = doc.Log_Actions & "," & "Field QCR_Qty is changed"
End Select
End If
Next
End If
End Sub
doc.Log_Actions returns the notesitem. To access the value you need to use doc.Log_Actions(0)
In LotusScript back-end classes (e.g. NotesDocument, NotesItem), a multi-valued field is represented by an array with one value per element of the array. For setting the value of a field, doc.Log_Actions is shorthand (they call it 'extended syntax' in the Domino Designer help) for assigning the first (i.e., zero subscript) element of the array, but that does not work for getting the value. To get the first value, you have to use doc.Log_Actions(0). To get or set the second value, you have to use doc.Log_Actions(1).
So, your Case 2 code could look like this:
doc.Log_Actions(1) = "Field QCR_Qty is changed"
My guess, however, is that you really want to be able to continually append to the end of the list of values each time this code runs. You are also going to want your code to be robust and not blow up on you if (for any reason!) the Log_Actions item does not exist in the document. For that, you are going to want to do this:
dim actionsItem as NotesItem
if doc.hasItem("Log_Actions") then
set actionsItem = doc.getFirstItem("Log_Actions")
call actionsItem.AppendToTextList("Field QCR_Qty is changed")
end if
Or,
If (Not doc.HasItem("LogActions")) Then
doc.LogActions = "Field QCR_Qty is changed"
Else
doc.LogActions = ArrayAppend(doc.LogActions,"Field QCR_Qty is changed")
End If
This is equivalent to the NotesItem method by rhsatrhs, which you use is matter of preference.

Resources