How to join substrings to define integer variable? - vba

I am trying to join two substrings into one that defines an integer variable.
Example:
Dim ACTGPA as Integer
Dim ACTGPB as Integer
Dim ACPrio as Integer
ACTGPA = 5
ACTGPB = 10
Following a lot of code I have a loop that selects the value from a recordset containing a number column called either "TGP_A" or TGP_B".
Set rs4 = db.OpenRecordset("SELECT * FROM tbl_Syllabus WHERE Mis_Name = '" & strMisName & "'")
Dim item As Variant
For Each item In rs4.Fields
If item.Name = "TGP_A" Or item.Name = "TGP_B" Then
If Nz(rs4(item.Name).Value, "") > 0 Then
If strACCon1 = "" Then
strACCon1 = item.Name
End If
End If
End If
Next item
I want to set the ACPrio value to either the value of ACTGPA or ACTGPB, depending on which item name is chosen in the loop.
Using replace I remove the _ from the item name in order to define ACTGPA (or B).
I get
"Error 13, type mismatch"
on this next line. Probably because it thinks I am trying to set ACPrio (integer) to something that is a string - but I am trying to write the integer ACTGPA (or ACTGPB).
ACPrio = "AC" & Replace(strACCon1, "_", "")
Should be the same as this:
ACPrio = ACTGPA 'eg. settings the ACPrio value to that of ACTGPA (or ACTGPB), which is 5 (or 10).

You can't use a string to reference a variable (or its value) by name.
But you can add the necessary values to a collection with their name and then access them later on by name, like in this sample:
Public Sub Sample()
Dim ACTGPA As Integer
Dim ACTGPB As Integer
Dim ACPrio As Integer
ACTGPA = 5
ACTGPB = 10
' Prepare the collection by adding the values with their name:
Dim col As Collection
Set col = New Collection
col.Add 5, "ACTGPA"
col.Add 10, "ACTGPB"
Dim strACCon1 As String
' Set for testing to "TGP_A":
strACCon1 = "TGP_A"
ACPrio = col("AC" & Replace(strACCon1, "_", ""))
Debug.Print ACPrio
' Set for testing to "TGP_B":
strACCon1 = "TGP_B"
ACPrio = col("AC" & Replace(strACCon1, "_", ""))
Debug.Print ACPrio
End Sub
The output is
5
10
And maybe you can omit the variables ACTGPA and ACTGPB at all now, if it fits to your concept and overall code.

Related

Does the textbox that is generated when creating a detail view not count as a textbox?

My code searches for certain numbers in textboxes and replaces them. The code however does not change the number if it is in a textbox that is created from a detail view(see figure 1). Do these not count as textboxes?
Figure 1
Dim Totalsheets As Integer
Dim target_text As String
Dim FirstPage As Integer
Dim replace_text As String
Dim result As String
Dim n As Integer 'count No. of text frames changed
Dim i As Integer 'count views for the sheet
Dim x As Integer 'takes the value of the first page of the old config
Dim y As Integer 'takes the value of the total number of sheets of the old config
Dim z As Integer 'takes the value of the number that needs to be added to update the zoning
Dim a As String 'takes the value of the letter found in the zoning box
Dim b As Integer
n = 0
Set osheets = odoc.Sheets
Set osheets = osheets.Item("DRAFT") 'makes sure only sheet "DRAFT" is edited
Set oViews = osheets.Views
Totalsheets = Totalsheets1.Value 'draws value from the textbox
FirstPage = FirstPage1.Value 'draws value from the textbox
For i = 3 To oViews.Count 'scans through all views in sheet
Set oView = oViews.Item(i)
Set oTexts = oView.Texts
For Each SrcText In oTexts 'scans through all text in view
x = FirstPage
y = Totalsheets
b = x + y
Do Until x = b + 1
z = x + Totalsheets
a = "A"
Do Until a = "[" 'goes from A to Z
result = SrcText.Text
target_text = " " & x & a 'gets space in front and letter at back to ensure only zone box are updated
replace_text = " " & z & a
If InStr(result, target_text) Then
result = Replace(result, target_text, replace_text)
SrcText.Text = result
n = n + 1
End If
a = Chr(Asc(a) + 1)
Loop
x = x + 1
Loop
Next
Next
Although the detail view identifier is a DrawingText, it does not belong to the DrawingTexts-collection.
You could access the DrawingText by searching in the view.
Better would be to rename the property of the view.
EDIT:
Example for using the (slower) selection:
Set oSel = oDoc.Selection
oSel.Clear
oSel.Add oView
oSel.Search "CATDrwSearch.DrwText,sel"
for i = 1 to oSel.Count2
Set oDrwText = oSel.Item2(i).Value
'do something with the text
next

Nested dictionary object not found

I am attempting to take some table, a list of fields to group by, and a number field as input, to produce an output table that contains the group-by fields and medians for the number field.
I have this working for a single field to group by, but not multiple fields.
I am using nested dictionaries to eventually aggregate my grouped-field values and their medians.
When I try to access the inner dictionary I get a
'424' Run-time error: Object required
Once I put the inner dictionary in the outer dictionary I cannot access it like one would suspect.
Public Sub MedianByGroups(ByVal inputTable As String, ByVal strField As String, _
ByVal strGroup As String, ByVal outputTable As String, _
Optional ByVal strCriteria As String)
DoCmd.SetWarnings False
Dim db As DAO.Database: Set db = CurrentDb()
Dim rstDomain As DAO.Recordset
Dim strSQL As String
Dim varMedian As Long: varMedian = 0
Dim intRecords As Long
Dim splitgroup As Variant
splitgroup = Split(strGroup, ", ")
strSQL = "SELECT DISTINCT " & strGroup & " INTO TMP_GROUPINGTABLE FROM " & _
inputTable & ";"
DoCmd.RunSQL (strSQL)
Set rstDomain = db.OpenRecordset("TMP_GROUPINGTABLE")
Dim i As Integer: i = 0
Dim group_dict As New Dictionary
Dim tmp_dict As Dictionary
Set tmp_dict = New Dictionary
If Not (rstDomain.EOF And rstDomain.BOF) Then
rstDomain.MoveFirst
Do Until rstDomain.EOF = True
For Each Label In splitgroup
tmp_dict.Add Label, rstDomain.Fields(Label).Value
Next Label
group_dict.Add i, tmp_dct
Set tmp_dict = New Dictionary
i = i + 1
rstDomain.MoveNext
Loop
End If
rstDomain.Close
For Each key In group_dict.Keys
For Each addlKey In group_dict(key).Keys
Debug.Print addlKey, group_dict(key)(addlKey)
Next addlKey
Next key
DoCmd.SetWarnings True
end sub
If one had a table, called "MYTABLE", that looked like this:
GROUP1 GROUP2 VAL1
A C 400
B D 500
One would call this sub like:
call MedianByGroups("MYTABLE", "VAL1', "GROUP1, GROUP2", "OUTPUTTABLE")
This doesn't do the Median or any other parts yet, as I am hitting this stumbling point with the dictionaries.
Where it fails is the inner for loop on that nested for loop near the end.
For Each addlKey In group_dict(key).Keys
Edit: As ComputerVersteher pointed out, the issue was a spelling mistake I had made. The solution to avoid this as Andre mentioned is to add the option explicit to the module.
Not a complete answer -- I set up an example without the MS Access-specific parts and the logic in your code seems to run fine. As near as I can tell, there's no real difference in the logic below and your code above. Does this example run for you?
Option Explicit
Sub TestingNestedDictionaries()
Dim group_dict As New Dictionary
Dim tmp_dict As Dictionary
Set tmp_dict = New Dictionary
Dim labels As Variant
labels = Array("red", "orange", "yellow", "green", "blue", "indigo", "violet")
Dim i As Long
For i = 1 To 5
Dim label As Variant
For Each label In labels
tmp_dict.Add label, label & "-" & i
Next label
group_dict.Add i, tmp_dict
Set tmp_dict = New Dictionary
Next i
'--- pull out one color
' Const THIS_COLOR As String = "green"
' Dim group As Variant
' For Each group In group_dict
' Dim subDict As Dictionary
' Set subDict = group_dict(group)
' Debug.Print subDict(THIS_COLOR)
' Next group
Dim key As Variant
Dim addlKey As Variant
For Each key In group_dict.Keys
For Each addlKey In group_dict(key).Keys
Debug.Print addlKey, group_dict(key)(addlKey)
Next addlKey
Next key
End Sub

Excel VBA: MoviesByGenre Function

I am trying to write an Excel VBA function that will do two things. First, it will determine the number of movies in each genre and print it to the immediate window using the printMovieData function I have written. Secondly, it will return the genre that has the most number of movies using the FindMax function I have written. I have provided my codes for printMovieData, FindMax, and what I have so far for MoviesByGenre, however, I am not sure what I am doing wrong and am looking for help to get the function working. Currently, Excel is returning the #VALUE! error.
printMovieData:
Function printMovieData(title As String, arrayTopic, arrayOther)
printMovieData = ""
For i = 1 To UBound(arrayTopic)
Debug.Print arrayTopic(i) & " : " & arrayOther(i)
Next i
End Function
FindMax:
Function FindMax(valueArray, nameArray) As String
Dim i As Integer
Dim maxValue As Variant
maxValue = 0
For i = 1 To UBound(valueArray)
If valueArray(i) >= maxValue Then
maxValue = valueArray(i)
FindMax = nameArray(i)
End If
Next i
End Function
MoviesByGenre:
Function MoviesByGenre(genreRng As Range) As String
Dim i As Integer
Dim genreArray(1 To 4) As String
Dim countArray
genreArray(1) = Action
genreArray(2) = Comedy
genreArray(3) = Drama
genreArray(4) = Musical
For i = 1 To UBound(genreArray)
For j = 1 To genreRng.Count
If genreRng.Cells(j) = genreArray(i) Then
countArray(i) = countArray(i) + 1
End If
Next j
Next i
MoviesByGenre = printMovieData("Movies by Genre", genreArray, countArray)
MoviesByGenre = FindMax(countArray, genreArray)
End Function
TBH there are quite a lot of reasons why I wouldn't expect your code to work.
There are some assumptions made such as how you use genreRng.Count. This is assuming data to count is either one row or one column.
The following assumes that genreRng.Cells.Count, Ubound(genreArray) and UBound(countArray) are all the same. You don't ensure this.
There are missing variable declarations, no use of Option Explicit and a number of other things.
Overarching though, is that I think you want a different object to handle your count. This is where Collection and Scripting Dictionaries are very useful.
You can have the key as the genre and the count is held in the associated value. If the key already exists, i.e. a repeat genre, just add one to the existing count.
With that in mind, a starting point, might be something like (sorry, no error handling added):
Option Explicit
Public Sub test()
Dim genreCount As Object
Set genreCount = CreateObject("Scripting.Dictionary")
Set genreCount = MoviesByGenre(ActiveSheet.Range("A1:A3"), genreCount)
printMovieData "Movies by genre", genreCount
FindMax genreCount
End Sub
Public Function MoviesByGenre(ByRef genreRng As Range, ByVal genreCount As Object) As Object
Dim j As Long
For j = 1 To genreRng.Count 'assumes 1 column/row
Dim currentGenre As String
currentGenre = genreRng.Cells(j, 1)
If Not genreCount.Exists(currentGenre) Then
genreCount.Add currentGenre, 1
Else
genreCount(currentGenre) = genreCount(currentGenre) + 1
End If
Next j
Set MoviesByGenre = genreCount
End Function
Public Function printMovieData(ByVal title As String, ByVal genreCount As Object)
Dim key As Variant
Debug.Print title & vbCrLf 'put to next line
For Each key In genreCount.keys
Debug.Print key & " : " & genreCount(key)
Next key
End Function
Public Function FindMax(ByVal genreCount As Object) As String
Dim maxValue As Long
Dim maxGenre As String
Dim key As Variant
For Each key In genreCount.keys
If genreCount(key) > maxValue Then
maxValue = genreCount(key)
maxGenre = key
End If
Next key
Debug.Print vbNewLine & "Max genre is " & maxGenre & " with " & maxValue
End Function
Input and output:
Input:
Output:

In string search for number to determine next in sequence?

I have a list of build numbers (e.g. R1079-AAA-001, ...-002 etc.) in which the value of "R1079" changes depending on the machine being used. What I want to do is search through the list to determine the last used build number (the last 3 digits) in relation to the specific machine I intend to use. I then need to add one and create a new log for the new build i.e. the last R1079 build was 056, therefore the new one is 057.
Currently the THEORY I have is an in string search for the machine number followed by a number search and store in the string and converted to integer. This is then added into a dynamic array and the maximum found when the loop is complete. One is added to this integer and the new name placed into a cell.
However, the code I have doesn't work so I assume I am missing things/got it all wrong.
Code below:
Sub test()
Dim x As String
Dim n As Integer
Dim i As Integer
Dim Machine_EBM As String
Dim retval As String
Dim retvalint As Integer
Dim LastBuild As Integer
Dim NextBuild As Integer
Dim myarr() As Integer
Machine = "R1079"
x = Cells("A1").Value 'get the first string in the list
n = 1
Do Until x = ""
If InStr(x, Machine) > 0 Then 'search for machine in string
For i = 6 To Len(Str) 'search for numbers at end of string
If Mid(x, i, 1) >= "0" And Mid(x, i, 1) <= "9" Then
retval = retval + Mid(s, i, 1) 'store numbers
End If
Next i
retvalint = CInt(retval) ' convert to integer
ReDim Preserve myarr(n)
myarr(n) = retvalint ' store integer value in array
n = n + 1
End If
Loop
LastBuild = Worksheet.Function.Max(myarr(n)) ' determine maximum array value
NewBuild = LastBuild + 1 'add one to the value
Range("C1").Select
ActiveCell = Machine = "-AAA-" + NewBuild 'input new build number
End Sub
I am fairly new to VBA and self taught so I realise there may be a lot of errors here that I am missing. Any help is appreciated!
Thanks,
Charlie
Here is a small piece of code for getting new build no for inputted build no.
I already tested the code. It give me right answer. So, you can use this code.
Public Sub getBuildNo()
Dim machineCode, lastBuildCode, newBuildCode As String
Dim buildNo As Integer
'Set machine code
machineCode = "R1079"
'Set last build code
lastBuildCode = Range("A1")
'Get last build no
buildNo = Right(lastBuildCode, 3)
'Increase 1
buildNo = buildNo + 1
'Get new build No
newBuildCode = machineCode & "-AAA-"
'adding prefix 0s for getting like (001, 002, 025, etc.)
If buildNo < 10 Then
newBuildCode = newBuildCode & "00" & buildNo
ElseIf buildNo < 100 Then
newBuildCode = newBuildCode & "0" & buildNo
Else
newBuildCode = newBuildCode & buildNo
End If
'show new code
Range("C1") = newBuildCode
End Sub

Separating Delimited Variable into array elements in VB.NET

I long variable in vb.net which contains the following information,
Dim g As String = "$C:\Program Files\Cavaj Java Decompiler\cavaj.exe$C:\Users\Yoosuf\AppData\Local\Google\Chrome\Application\chrome.exe$C:\Program Files\DVD Maker\dvdmaker.exe$C:\Program Files\Adobe\Adobe Photoshop CS2\ImageReady.exe$C:\Program Files\Java\jre6\bin\javaws.exe$"
The $ symbol is used as a delimiter to separate each item from the other. I need to add the exe file name at the end of each path to a listbox. However the initial process of retrieving the variable to individual array elements is not working properly.
Dim strArr() As String = g.Split("$") 'This variable is empty
For count = 0 To strArr.Length - 1
Dim arr As String = strArr(count).Split("\")
Dim strval As String = ""
For i As Integer = 3 To arr.Length - 1
strval = arr(i)
Dim j As Integer = arr.Length - 1
strval = arr(j)
Dim result As String = strval.Substring(g.Length - 5)
result = g.Substring(g.LastIndexOf("\") + 1)
ListBox1.Items.Add(result)
Next
Next
No need to do all this work. The System.IO.Path class has methods to do this for you. You want to use either System.IO.Path.GetFileName or System.IO.Path.GetFileNameWithoutExtension. Since you've already split all the file paths, just pass those paths to either of the aforementioned methods and add the result to your listbox.
Dim strArr() As String = g.Split("$")
For Each path As String In strArr
ListBox1.Items.Add(System.IO.Path.GetFileName(path))
Next
Please refer to the code below and the associated comments. Also I have comment out some code which I feel is not required based on what you want to do.
Dim strArr() As String = g.Split("$") 'This variable is empty
For count = 0 To strArr.Length - 1
Dim arr() As String = strArr(count).Split("\") ' Split returns an array
Dim strval As String = ""
For i As Integer = 3 To arr.Length - 1
'strval = arr(i)
Dim j As Integer = arr.Length - 1
strval = arr(j)
'Dim result As String = strval.Substring(g.Length - 5)
'result = g.Substring(g.LastIndexOf("\") + 1)
ListBox1.Items.Add(strval)
Next
Next