How do I reference array items in a dictionary? - excel

I am trying to determine if any one of the strings inside any one of the array items in a VBA dictionary equal a string of 4 spaces.
If _
Not CStr(info.Items(1, 4)) = " " Or _
Not CStr(info.Items(1, 5)) = " " Or _
Not CStr(info.Items(1, 6)) = " " Or _
Not CStr(info.Items(2, 4)) = " " Or _
Not CStr(info.Items(2, 5)) = " " Or _
Not CStr(info.Items(2, 6)) = " " Or _
Not CStr(info.Items(3, 4)) = " " Or _
Not CStr(info.Items(3, 5)) = " " Or _
Not CStr(info.Items(3, 6)) = " " Or _
Not CStr(info.Items(4, 4)) = " " Or _
Not CStr(info.Items(4, 5)) = " " Or _
Not CStr(info.Items(4, 6)) = " " Then
I keep getting a Subscript out of range error. I've tried
...info.Items(1)(4)... as well with the same error.
I know each array item has 6 elements in it, and I know there are 4 keys in the dictionary. How do I access elements of each key's item if the item is an array?
Dim RQItems As Dictionary
Dim RPItems As Dictionary
Dim IMPItems As Dictionary
Dim EMItems As Dictionary
Dim BOOTItems As Dictionary
Dim RQ1(6) As String
Dim RQ2(6) As String
Dim RQ3(6) As String
Dim RQ4(6) As String
Set RQItems = New Dictionary
RQ1(1) = "PSA "
RQ1(2) = "Prlm"
RQ1(3) = "Info"
RQ1(4) = " "
RQ1(5) = " "
RQ1(6) = " "
RQ2(1) = "Mary"
RQ2(2) = "Clnt"
RQ2(3) = "Escr"
RQ2(4) = "Bank"
RQ2(5) = " SS "
RQ2(6) = " "
RQ3(1) = "Inst"
RQ3(2) = "Wire"
RQ3(3) = " "
RQ3(4) = " "
RQ3(5) = " "
RQ3(6) = " "
RQ4(1) = "Acct"
RQ4(2) = "Fee "
RQ4(3) = " "
RQ4(4) = " "
RQ4(5) = " "
RQ4(6) = " "
RQItems("OPEN") = RQ1
RQItems("DOCS") = RQ2
RQItems("$$$$") = RQ3
RQItems("FILE") = RQ4
I pass these into a function like myFn(info As Dictionary)

You can access arrays stored in a dictionary like this:
Sub Test()
Dim dict As New Dictionary, arr(1 To 4), k, arr2, v
arr(1) = "One"
arr(2) = "Two"
arr(3) = "Three"
arr(4) = "four"
dict.Add "Test", arr
'access a single item
Debug.Print dict("Test")(1) '>> One
'loop over all contained arrays
For Each k In dict.Keys
arr2 = dict(k)
Debug.Print arr2(3) 'access a single element
'or loop through all elements in the array
For Each v In arr2
Debug.Print k, v
Next v
Next k
End Sub

Related

Getting a method or data member not found in a class module

Here is the code for the class module (where it errors on the code module):
Private Sub CommandButton_Click()
Dim VBAEditor As VBIDE.VBE
Dim VBProj As VBIDE.VBProject
Dim VBComp As VBIDE.VBComponent
Dim CodeMod As VBIDE.CodeModule
Dim mdl As Object
Dim mdl_exits As Boolean
Dim mdl_name As String
Dim macro_name As String
Dim macro_exists As Boolean
mdl_name = "SaveButtons"
For Each mdl In ThisWorkbook.VBProject.VBComponents
If mdl.Name = mdl_name And mdl.Type = 1 Then
Set prrf_Module = mdl
mdl_exists = True
Exit For
End If
Next
If mdl_exists Then GoTo it_exists
Set prrf_Module = ThisWorkbook.VBProject.VBComponents.Add(1)
prrf_Module.Name = mdl_name
it_exists:
macro_exists = False
macro_name = SaveButton.Value
new_name:
If macro_exists = True Then
If macro_name = SaveButton.Value Then
macro_name = SaveButton.Value & "1"
Else
macro_name = Left(macro_name, Len(macro_name) - 1) & CInt(Mid(macro_name, Len(macro_name) - 1)) + 1
End If
End If
macro_exists = False
zy = "Userform1.show"
strMacro = "Sub " & "CommandButton1" & vbCr
strMacro = strMacro & " " & zy & vbCr
strMacro = strMacro & "End Sub" & vbCr
Debug.Print "strMacro is " & vbCr & strMacro
'Set prrf_Module = ThisWorkbook.VBProject.VBComponents.Add(1)
Dim d, e, f, y
For y = 1 To 2
With btn_Gen.CodeModule
d = .CountOfLines
.insertlines 1, "Sub CommandButton" & y & "_Click()"
For e = LBound(t) To UBound(t)
countlines = countlines + 1
upper = UBound(t)
xy = countlines + 1
.insertlines xy, " " & t(e)
Next e
.insertlines xy + 1, "End Sub"
End With
Next y
End Sub
And here is my module code (that runs till I click commandbutton1)
Sub showuserform1()
Dim x, y
Dim z() As String
Set btn_nm = New Scripting.Dictionary
Set lbl_tx = New Scripting.Dictionary
Set code = New Scripting.Dictionary
repeatx:
x = UCase(InputBox("(H)orizontal or (V)ertical?", "Orientation", "H"))
If x = "H" Then
orientation = "Horizontal"
ElseIf x = "V" Then
orientation = "Vertical"
Else
MsgBox ("Input either 'H' or 'V'")
GoTo repeatx
End If
repeatcount:
count = InputBox("How many buttons do you want? ", "Button Count", "1")
If count < 1 Then
MsgBox ("Input Quantity of Buttons, enter at least 1")
GoTo repeatcount:
End If
For y = 1 To count
btn_nm(y) = InputBox("What do you want CommandButton" & y + 1 & " to say?", "CommandButton name", "CommandButton" & y)
lbl_tx(y) = InputBox("What do you want Label" & y + 1 & " to say?", "Label text", "Label" & y)
btn_Gen_uf2.Label1.Caption = "Enter Code in Window - max 8k characters"
btn_Gen_uf2.TextBox1.Value = ""
repeatshow:
btn_Gen_uf2.TextBox1.SetFocus
btn_Gen_uf2.Show
If btn_Gen_uf2.TextBox1.Value = "" Then
MsgBox "Enter Code in Window before selecting OK"
GoTo repeatshow:
End If
t = Split(btn_Gen_uf2.TextBox1.Text, vbCrLf)
ReDim z(0 To UBound(t), 1 To count)
For w = LBound(t) To UBound(t)
MsgBox t(w)
'Debug.Print "z(" & w & "," & y & ") = " & t(w)
z(w, y) = t(w)
Next w
Next y
' Do this last
btn_Gen.Show
End Sub
This is crossposted from excelforum.
I added the declarations (see above) and now am getting an error on this line: Dim VBAEditor as VBIDE.VBE
The error is "User-defined type not defined". Am I missing a reference?
With rory's help, I made this one change and most of the code is working.
With Prrf_Module.CodeModule
instead of
With btn_Gen.Codemodule

Extracting Text from PDF - Excel VBA

I have code that was written for me and it works perfect for four of the entries I am wanting to find, but is there a way that I can add another field value to search for, like ID? I have tried to change the code for what I think would work, but I got errors. I have never coded something this complex, so I do not understand fully what the author did in each section.
Option Explicit
Public Sub ExtractFieldValues()
Const CONSTLAST As Long = 1
Const CONSTFIRST As Long = 2
Const CONSTMIDDLE As Long = 3
Const CONSTRANK As Long = 4
Const TABLEONE As String = "Table 1"
Const FIELDVALUES As String = "FieldValues"
Const LAST_FIRST_MIDDLE As String = "last first middle"
Const FIELDNAMES As String = LAST_FIRST_MIDDLE & " rank"
Const NUMRECORDS As Long = 5 '6
Dim ƒ As Excel.WorksheetFunction: Set ƒ = Excel.WorksheetFunction
Dim ¡ As Long
Dim lrd As Long
Dim nextRowOutput As Long
Dim arngFoundCells(CONSTLAST To CONSTRANK) As Range
Dim varFoundCell As Variant
Dim lngFirstFoundRow As Long
Dim lngNextFoundRow As Long
Dim rngNextFindStart As Range
Dim dictFields As Object
Dim astrFieldNames() As String
Dim astrSplitValues() As String
Dim strFoundValue As String
Dim lngFieldCount As Long
Set dictFields = CreateObject("Scripting.Dictionary")
dictFields.CompareMode = vbTextCompare
With Worksheets
On Error Resume Next
.Add(After:=.Item(.count)).name = FIELDVALUES
On Error GoTo 0
Application.DisplayAlerts = False
If .Item(.count).name <> FIELDVALUES Then
.Item(.count).Delete
.Item(FIELDVALUES).UsedRange.Clear
End If
Application.DisplayAlerts = True
.Item(TABLEONE).Activate
End With
astrFieldNames = Split(" " & FIELDNAMES, " ") ' Force index zero to a blank -> treat as base 1
Set dictFields = CreateObject("Scripting.Dictionary")
For ¡ = CONSTLAST To CONSTRANK
dictFields.Add astrFieldNames(¡), ""
Next ¡
lrd _
= Cells _
.find _
( _
What:="*" _
, After:=Cells(1) _
, LookIn:=xlFormulas _
, Lookat:=xlPart _
, SearchOrder:=xlByRows _
, SearchDirection:=xlPrevious _
) _
.Row
With Range(Rows(1), Rows(lrd))
For ¡ = CONSTLAST To CONSTRANK
Set arngFoundCells(¡) = .find(What:=astrFieldNames(¡), After:=Cells(1))
Next ¡
lngFirstFoundRow _
= ƒ.Min _
( _
arngFoundCells(CONSTLAST).Row _
, arngFoundCells(CONSTFIRST).Row _
, arngFoundCells(CONSTMIDDLE).Row _
)
nextRowOutput = 1
Do
For ¡ = CONSTLAST To CONSTRANK
' Debug.Print arngFoundCells(¡).Address; " ";
dictFields.Item(astrFieldNames(¡)) = ""
Next ¡
' Debug.Print
Select Case True
Case arngFoundCells(CONSTFIRST).Row = arngFoundCells(CONSTMIDDLE).Row:
If arngFoundCells(CONSTRANK).Row <> arngFoundCells(CONSTFIRST).Row Then
Set arngFoundCells(CONSTRANK) = arngFoundCells(CONSTFIRST)
End If
For Each varFoundCell In arngFoundCells
strFoundValue = ƒ.Trim(Replace(varFoundCell.Value2, vbLf, " ")) & " "
If strFoundValue Like "[']*" Then strFoundValue = Mid$(strFoundValue, 2)
If LCase$(strFoundValue) Like astrFieldNames(CONSTLAST) & " " Then
strFoundValue = ƒ.Trim(strFoundValue & Rows(varFoundCell.Row + 1).Cells(1).Value2) & " "
End If
If LCase$(strFoundValue) Like LAST_FIRST_MIDDLE & "*" _
And Len(strFoundValue) - Len(Replace(strFoundValue, " ", "")) < 5 _
Then
strFoundValue = ƒ.Trim(strFoundValue & Rows(varFoundCell.Row + 1).Cells(1).Value2) & " "
End If
astrSplitValues = Split(" " & strFoundValue, " ") ' Force index zero to a blank -> treat as base 1
lngFieldCount = Int(UBound(astrSplitValues) / 2)
For ¡ = 1 To lngFieldCount
dictFields.Item(LCase(astrSplitValues(¡))) = astrSplitValues(¡ + lngFieldCount)
Next ¡
Next varFoundCell
Case Else
Debug.Print " SKIPPED: ";
For ¡ = CONSTLAST To CONSTRANK
Debug.Print arngFoundCells(¡).Address; " ";
Next ¡
Debug.Print
For ¡ = CONSTLAST To CONSTRANK
Debug.Print " "; ƒ.Trim(arngFoundCells(¡).Value2)
Next ¡
Debug.Print
End Select
Sheets(FIELDVALUES).Columns(1).Cells(nextRowOutput).Resize(4).Value _
= ƒ.Transpose(dictFields.Items)
nextRowOutput = nextRowOutput + NUMRECORDS
Set rngNextFindStart = Rows(arngFoundCells(CONSTFIRST).Row + 2).Cells(1)
For ¡ = CONSTLAST To CONSTRANK
Set arngFoundCells(¡) = .find(What:=astrFieldNames(¡), After:=rngNextFindStart)
Next ¡
lngNextFoundRow _
= ƒ.Min _
( _
arngFoundCells(CONSTLAST).Row _
, arngFoundCells(CONSTFIRST).Row _
, arngFoundCells(CONSTMIDDLE).Row _
)
Loop While lngNextFoundRow <> lngFirstFoundRow
End With
End Sub

mixing subscript in a string

in a VBA excel macro I am using, I have the following code:
For k = MinDeg To MaxDeg
OutputStr = Trim(OutputStr & "a" & Str(k) & " = " & _
Str(MyCoe) & " ± " & _
Str(MyErr) & Chr(10))
Next k
Where "MyCoe" and "MyErr" are given numbers, and "minDeg" and "MaxDeg" are integers.
My question is:
How can I make "Str(k)" appear in the outputstr as subscript text?
If Unicode is available in your environment, another option would be to use the subscripted Unicode characters for Str(K). Making some modifications to Gary's Student code so as to get output in A1:
Option Explicit
Sub foo()
Dim K As Long
Const MinDeg As Long = 10
Const MaxDeg As Long = 13
Dim sK As String, I As Long
Const MyCoe As Long = 3
Const MyErr As Long = 5
Dim OutPutStr As String
For K = MinDeg To MaxDeg
sK = ""
For I = 1 To Len(CStr(K))
sK = sK & ChrW(832 & Mid(CStr(K), I, 1))
Next I
OutPutStr = Trim(OutPutStr & "a" & sK & " = " & _
Str(MyCoe) & " ± " & _
Str(MyErr) & Chr(10))
Next K
Cells(1, 1) = OutPutStr
End Sub
Note that the subscripted values also appear in the formula bar.
First I run this simple mod to your code:
Sub WhatEverr()
mindeg = 10
maxdeg = 13
mycoe = 3
myerr = 5
For k = mindeg To maxdeg
outputstr = Trim(outputstr & "a" & Str(k) & " = " & _
Str(mycoe) & " ± " & _
Str(myerr) & Chr(10))
Next k
Range("A1").Value = outputstr
End Sub
to get this in A1:
Then I run:
Sub formatcell()
Dim i As Long, L As Long, rng As Range
Dim s As String
Set rng = Range("A1")
s = rng.Value
L = Len(s)
For i = 1 To L
ch = Mid(s, i, 1)
If ch = "a" Then
rng.Characters(Start:=i + 2, Length:=2).Font.Subscript = True
End If
Next i
End Sub
To apply the format:
In Excel, this type of character formatting is a property of the Range object. You do not build it into the string like you would in HTML.

Arrays- Subscript Out of range Error- Access VBA

I am new to coding in Access VBA. I am trying to run the following code to extract the selected records from an Access Table and export them to excel but it keeps on showing me the 'Subscript out of range' error.This is the part of the code where I am getting an error. Any help would be appreciated. Thank you
Set db = CurrentDb()
Set rec = db.OpenRecordset("Tablename", dbOpenDynaset)
Dim k As Integer
Dim n() As Variant
Dim m() As Variant
Dim p() As Variant
Dim q() As Variant
Dim size As Integer
k = 10
i = 1
If Not rec.EOF Then
rec.MoveFirst
rec.FindFirst ("Variable1 = '" & Me.Variable1.Value & "' AND Variable2 = " & Me.Variable2.Value & " AND Variable3 = '" & Me.Variable3.Value & "'")
size = DCount("[Field4]", "Tablename", "Variable1 = '" & Me.Variable1.Value & "' AND Variable2 = " & Me.Variable2.Value & " AND Variable3 = '" & Me.Variable3.Value & "'")
ReDim n(size) As String
ReDim m(size) As String
ReDim p(size) As String
ReDim q(size) As String
Do Until rec.EOF
If Not IsNull(rec.Fields("Field4")) Then
n(i) = rec.Fields("Field4")
WKS.Cells((k), 1) = n(i)
End If
If Not IsNull(rec.Fields("Field3")) Then
m(i) = rec.Fields("Field3")
WKS.Cells((k), 2) = m(i)
End If
If Not IsNull(rec.Fields("Field2")) Then
p(i) = rec.Fields("Field2")
WKS.Cells((k), 3) = p(i)
End If
If Not IsNull(rec.Fields("Field1")) Then
q(i) = rec.Fields("Field1")
WKS.Cells((k), 4) = q(i)
End If
rec.MoveNext
k = k + 1
i = i + 1
Loop
End If
Set rec = Nothing

Changing word color to red based on list of words

I have the following code which allows me to change one word to a different color. Is there a way to change multiple words to different colors so I don't have to set up the macro for 100 different words, and then run the macro 100 different times?
For example - this is the code when searching for word 'dog'. Can I also add in 'cat' somehow?
Sub test()
Dim changeRange As Range, oneCell As Range
Dim testStr As String, seekstr As String
Dim startPosition As String
seekstr = "dog": Rem adjust
Set changeRange = ThisWorkbook.Sheets("Sheet1").Range("A2:B21"): Rem adjust
For Each oneCell In changeRange.Cells
testStr = CStr(oneCell.Value)
testStr = LCase(testStr): seekstr = LCase(seekstr): Rem For Case insensitive
oneCell.Font.ColorIndex = xlAutomatic: Rem remove all colors
startPosition = 1
Do While 0 < InStr(startPosition, " " & testStr & " ", " " & seekstr & " ", 1)
startPosition = InStr(startPosition, " " & testStr & " ", " " & seekstr & " ") + 1
oneCell.Characters(startPosition - 1, Len(seekstr)).Font.ColorIndex = 3
Loop
Next oneCell
End Sub
Work with an array of pets. After getting to each individual cell, cycle through the array, testing each value and adjusting the text color as necessary.
Sub test()
Dim changeRange As Range, oneCell As Range
Dim testStr As String, seekstr As String
Dim startPosition As String
Dim v As Long, vPETs As Variant
vPETs = Array("dog", "cat", "hamster")
Set changeRange = ThisWorkbook.Sheets("Sheet1").Range("A2:B21"): Rem adjust
For Each oneCell In changeRange.Cells
testStr = CStr(oneCell.Value)
testStr = LCase(testStr): seekstr = LCase(seekstr): Rem For Case insensitive
oneCell.Font.ColorIndex = xlAutomatic: Rem remove all colors
For v = LBound(vPETs) To UBound(vPETs)
seekstr = vPETs(v)
startPosition = 1
Do While 0 < InStr(startPosition, " " & testStr & " ", " " & seekstr & " ", 1)
startPosition = InStr(startPosition, " " & testStr & " ", " " & seekstr & " ") + 1
oneCell.Characters(startPosition - 1, Len(seekstr)).Font.ColorIndex = 3
Loop
Next v
Next oneCell
End Sub

Resources