I've just gotten into programming VBA, and have very little other programming experience.
I'll first describe the intention of the macro:
So, there are an x number of excel files with data in them. All these files follow the same basic design:
Column A contains the 'name' of the data I want. There are ten rows with different names.
Column M contains the data corresponding to the name of column A (an average value of the columns in between)
This average data has to be transferred to a 'master' excel file.
I've made a userform to select the files that need to be imported, which appears to work fine (at least selecting the files)
I call the userform within my module using
usrform.show
As said, I'm able to run the userform. Just when I click apply within the userform, it stops the code and opens the excel vba editor and displays the graphical userform.
No idea what's causing this. Do Any of you have input?
Public strListe_selected() As String
Public booDatenAbbrechen As Boolean
Sub Ergebnisse_einlesen()
Dim datei As String
Dim liste As String
Dim test As Variant
Dim name As String
Dim nPh As Integer
Dim Suche As String
Dim Excel_Daten() As Variant
Dim rngFound As Range
Dim rngFound1 As Range
Dim Komponente() As String
Dim startreihe As Integer
Dim SMK As String
Dim dateinr As Integer
Dim strdatumformatiert As String
Dim strerstellungsdatum() As String
Dim intantwort As Integer
Dim strdatum As String
Dim Phase As String
'*************************************Zeit messen um Einlesezeit zu optimieren
Dim t
t = Now
'*************************************Zeile controlieren, somit kein daten in die falsche zeile kommt
startreihe = ActiveCell.Row
If startreihe < 10 Then
MsgBox "Bitte markieren sie die Zeile in der die neuen Testdaten eingetragen werden sollen und führen sie das Makro erneut aus"
Exit Sub
ElseIf Cells(startreihe, 3) <> "" Then
antwort = MsgBox("Die markierte Zeile enthält bereits Daten, wollen sie diese überschreiben?", vbOKCancel)
If antwort = vbCancel Then Exit Sub
End If
'************************************Sammeln von Informationen über diese Arbeitsmappe
liste = ThisWorkbook.ActiveSheet.name
letztespalte = ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Column
name = ThisWorkbook.name
'************************************Dialogfenster öffnen
xls_suchen.Show
If booDatenAbbrechen = True Then Exit Sub
For dateinr = 0 To UBound(strListe_selected) 'Schleife über die gewählten xls-Dateien
Application.ScreenUpdating = False 'Bildschirmanzeige unterdrücken
Workbooks.Open Filename:=Element & strListe_selected(dateinr) 'öffnen der xls-Datei
'**********************************************************************************************************************
'neudimensionieren des ARRAYs
c = 4
emdat = anzkomp * (c + 1)
ReDim Excel_Daten(24 + emdat, 3)
'Spaltenüberschrift des Arrays "Excel_Daten" festlegen
Excel_Daten(0, 0) = "Name"
Excel_Daten(0, 1) = "Reihe"
Excel_Daten(0, 2) = "Spalte"
Excel_Daten(0, 3) = "Wert"
'**********************************************************************************************************************
'******************************** Daten aus der Excel-Datei lesen *******************************************************
i = 2
For k = 1 To anzkomp
Suche = Komponente(k)
Excel_Daten(i, 0) = Komponente(k)
Set rngFound = Cells.Find(What:="Bemerkung:")
test = Cells(rngFound.Row, rngFound.Column).Value
If test = "Bemerkung:" Then
anzkomp = 11
nPh = 1
ReDim Komponente(anzkomp)
Testergebnis = "Phase"
Komponente(1) = "F_eth"
Komponente(2) = "F_Lakor_m"
Komponente(3) = "F_lradap1c[0]"
Komponente(4) = "F_lradap1c[1]"
Komponente(5) = "F_lradap1c[2]"
Komponente(6) = "F_lradap1c[3]"
Komponente(7) = "F_lradap1c[4]"
Komponente(8) = "F_lradap1c[5]"
Komponente(9) = "F_lradap1c[6]"
Komponente(10) = "F_lradap1c[7]"
Komponente(11) = "Km_st_1"
Else
MsgBox "Der test ist nicht bekannt. Ist der Datei ein EDR Messdatei?"
End If
Set rngFound1 = Cells.Find(What:="Phase")
If rngFound1 Is Nothing Then
MsgBox Testergebnis & "nicht gefunden"
Else
Set rngFound = Cells.Find(What:=Suche, After:=Cells(rngFound1.Row, rngFound1.Column))
If rngFound Is Nothing Then
If Suche = "F_eth" Then n = 2
If Suche = "F_Lakor_m" Then n = 5
If Suche = "F_lradap1c[0]" Then n = 8
If Suche = "F_lradap1c[1]" Then n = 11
If Suche = "F_lradap1c[2]" Then n = 14
If Suche = "F_lradap1c[3]" Then n = 17
If Suche = "F_lradap1c[4]" Then n = 20
If Suche = "F_lradap1c[5]" Then n = 23
If Suche = "F_lradap1c[6]" Then n = 26
If Suche = "F_lradap1c[7]" Then n = 29
If Suche = "Km_st_1" Then n = 32
For i = n To n + 4
If i <> n Then Excel_Daten(i, 0) = Suche & "_PH" & i - n
Excel_Daten(1, 3) = ""
Next i
Else
Excel_Daten(i, 1) = rngFound.Row
Excel_Daten(i, 2) = rngFound.Column
Excel_Daten(i, 3) = Cells(rngFound.Row, rngFound.Column + 12).Value
i = i + 1
For j = 1 To c
If j > nPh Then
If Suche = "F_eth" Then n = 2
If Suche = "F_Lakor_m" Then n = 5
If Suche = "F_lradap1c[0]" Then n = 8
If Suche = "F_lradap1c[1]" Then n = 11
If Suche = "F_lradap1c[2]" Then n = 14
If Suche = "F_lradap1c[3]" Then n = 17
If Suche = "F_lradap1c[4]" Then n = 20
If Suche = "F_lradap1c[5]" Then n = 23
If Suche = "F_lradap1c[6]" Then n = 26
If Suche = "F_lradap1c[7]" Then n = 29
If Suche = "Km_st_1" Then n = 32
Excel_Daten(n + j, 0) = Suche & "_PH" & j
Excel_Daten(n + j, 3) = ""
i = i + 1
End If
Next j
End If
End If
Next k
'Einlesen der Ergebnisse abgeschlossen --> schließen der VTS-Datei
ActiveWorkbook.Close
'**********************************************************************************************
'**********************************************************************************************
'Daten in gewünschtes Tabellenblatt übertragen
For b = 1 To 12
ThisWorkbook.Worksheets(liste).Cells(startreihe, b + 1) = Excel_Daten(b, 3)
Next b
b = 12
For a = 13 To 10 + emdat
ThisWorkbook.Worksheets(liste).Cells(startreihe, b + 3) = Excel_Daten(a, 3)
If Excel_Daten(a, 0) = "GRAMS_KM_CO2" Or Excel_Daten(a, 0) = "GRAMS_MI_CO2" _
Or Excel_Daten(a, 0) = "FUEL_CONS_MPG" Or Excel_Daten(a, 0) = "FUEL_CONS_KPL" _
Or Excel_Daten(a, 0) = "FUEL_CONS_LP100K" Then
b = b
ElseIf Excel_Daten(a + 1, 0) = Excel_Daten(a, 0) & "_PH1" Then
b = b + 2
End If
For i = 1 To c
a = a + 1
b = b + 1
ThisWorkbook.Worksheets(liste).Cells(startreihe, b + 3) = Excel_Daten(a, 3)
Next i
b = b + 1
'If a < emdat + 10 Then
' If test = "US06V1_FE" And VTS_Daten(a + 1, 0) = "FUEL_CONS_MPG" Then B = B + 5
'End If
Next a
Application.ScreenUpdating = True 'Bildschirmanzeige zulassen
Next dateinr
End Sub
Userform:
Private Sub button_cancel_Click()
ReDim strListe_selected(0) 'Liste wird gelöscht
booDatenAbbrechen = True
Unload Me
End Sub
Private Sub button_all_Click()
With Me.ListBox1
For i = 0 To .ListCount - 1
ListBox1.Selected(i) = True
Next
End With
End Sub
Private Sub button_none_Click()
With Me.ListBox1
For i = 0 To .ListCount - 1
ListBox1.Selected(i) = False
Next
End With
End Sub
Private Sub button_apply_Click()
booDatenAbbrechen = False
With Me.ListBox1
liste = .List
j = 0
For i = 0 To .ListCount - 1
If .Selected(i) Then
ReDim Preserve strListe_selected(j)
strListe_selected(j) = liste(i, 0)
j = j + 1
End If
Next
End With
Unload Me
End Sub
Private Sub button_add_file_Click()
add_files
End Sub
Private Sub button_add_folder_Click()
add_folder
End Sub
Sub add_folder()
Dim objAppShell As Object
Dim varBrowseDir As Variant
Dim strPfad As String
Dim varUnterordner As Variant
Dim objFileSystem As Object
Dim varOrdner As Variant
Dim Element
Dim strFilelist() As String
Dim i As Integer
Dim strFile As String
Dim FD As FileDialog
Set FD = Application.FileDialog(msoFileDialogFolderPicker)
With FD
.AllowMultiSelect = True
If Application.FileDialog(msoFileDialogFolderPicker).Show = 0 Then
Else
strPfad = .SelectedItems(1)
End If
End With
If strPfad = "" Then Exit Sub
'Ordner nach *.xls-Dateien durchsuchen
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Set varOrdner = objFileSystem.GetFolder(strPfad)
Set varUnterordner = varOrdner.SubFolders
i = 0
ReDim Preserve strFilelist(i)
'Hauptordner durchsuchen
strFile = Dir(strPfad & "\" & "*.xls") 'Ersten Eintrag wählen
Do While strFile <> ""
strFilelist(i) = strPfad & "\" & strFile
ListBox1.AddItem (strFilelist(i))
i = i + 1
ReDim Preserve strFilelist(i)
strFile = Dir 'strFile = Dir 'Get nächsten Eintrag.
Loop
'Unterordner durchsuchen
For Each Element In varUnterordner
strFile = Dir(strPfad & "\" & Element.name & "\" & "*.xls")
Do While strFile <> ""
ReDim Preserve strFilelist(i)
strFilelist(i) = strPfad & "\" & Element.name & "\" & strFile
ListBox1.AddItem (strFilelist(i))
i = i + 1
strFile = Dir 'strFile = Dir 'Get nächsten Eintrag.
Loop
Next
End Sub
Sub add_files()
Dim FD As FileDialog
Dim Element
Dim i As Integer
Set FD = Application.FileDialog(msoFileDialogOpen)
With FD
.AllowMultiSelect = True
'.InitialFileName = ActiveWorkbook.Path & "\*.xls"""
.Filters.Clear
.Filters.Add "Excel dateien", "*.xls"
End With
i = 1
If FD.Show = -1 Then
For Each Element In FD.SelectedItems
' datei = Dir(Element, "*.xls")
ListBox1.AddItem (FD.SelectedItems(i))
Next
End If
End Sub
Related
The goal is to provide a folder choosing dialogue to read file names and paste them into the open Word document with the file names being the title (above the picture). This is to ease step by step documentations in Word with a style of "1. Do this", "2. Do that" .... "10. And then that", "11. And then this" (with it being sorted wrong, i.e. 1, 10, 11, 13, 2, 3, 4, 5, 6, 7, 8, 9 without the sorting function).
I can't overcome the type mismatch error, that the following VBA code generates (it seems to be the error of String vs. Array type):
Function:
Function QuickSortNaturalNum(strArray() As String, intBottom As Integer, intTop As Integer)
Dim strPivot As String, strTemp As String
Dim intBottomTemp As Integer, intTopTemp As Integer
intBottomTemp = intBottom
intTopTemp = intTop
strPivot = strArray((intBottom + intTop) \ 2)
Do While (intBottomTemp <= intTopTemp)
' < comparison of the values is a descending sort
Do While (CompareNaturalNum(strArray(intBottomTemp), strPivot) < 0 And intBottomTemp < intTop)
intBottomTemp = intBottomTemp + 1
Loop
Do While (CompareNaturalNum(strPivot, strArray(intTopTemp)) < 0 And intTopTemp > intBottom)
intTopTemp = intTopTemp - 1
Loop
If intBottomTemp < intTopTemp Then
strTemp = strArray(intBottomTemp)
strArray(intBottomTemp) = strArray(intTopTemp)
strArray(intTopTemp) = strTemp
End If
If intBottomTemp <= intTopTemp Then
intBottomTemp = intBottomTemp + 1
intTopTemp = intTopTemp - 1
End If
Loop
'the function calls itself until everything is in good order
If (intBottom < intTopTemp) Then QuickSortNaturalNum strArray, intBottom, intTopTemp
If (intBottomTemp < intTop) Then QuickSortNaturalNum strArray, intBottomTemp, intTop
End Function
Sub:
Sub PicWithCaption()
Dim xFileDialog As FileDialog
Dim xPath, xFile, xFileNameOnly As String
Dim xFileNameOnlySorted, xFileNameOnlyUnsorted As Variant
Dim xFileNameOnlyUnsortedAsString As String
Dim i, k, l As Integer
l = 1
m = 100
On Error Resume Next
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
If xFileDialog.Show = -1 Then
xPath = xFileDialog.SelectedItems.Item(i)
If xPath <> "" Then
xFile = Dir(xPath & "\*.*")
For i = 0 To 100
Do While xFile <> ""
xFileNameOnly = Left(xFile, Len(xFile) - 4)
xFileNameOnlyUnsorted(i) = xFileNameOnly
ReDim Preserve xFileNameOnlyUnsorted(0 To i) As Variant
xFileNameOnlyUnsorted(i) = xFileNameOnlyUnsorted(i).Value
Loop
Next i
xFileNameOnlySorted = Module1.QuickSortNaturalNum(xFileNameOnlyUnsorted, l, m)
For xFileNameOnlySorted(k) = 1 To 100
If UCase(Right(xFileNameOnlySorted(k), 3)) = "PNG" Or _
UCase(Right(xFileNameOnlySorted(k), 3)) = "TIF" Or _
UCase(Right(xFileNameOnlySorted(k), 3)) = "JPG" Or _
UCase(Right(xFileNameOnlySorted(k), 3)) = "GIF" Or _
UCase(Right(xFileNameOnlySorted(k), 3)) = "BMP" Then
With Selection
.Text = xFileNameOnlySorted(k)
.MoveDown wdLine
.InlineShapes.AddPicture xPath & "\" & xFile, False, True
.InsertAfter vbCrLf
.MoveDown wdLine
End With
End If
Next xFileNameOnlySorted(k)
xFile = Dir()
End If
End If
End Sub
Here's a slightly different approach:
Sub PicWithCaption()
Dim xPath As String, colImages As Collection, arrFiles, f
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Select a folder with files to insert"
.AllowMultiSelect = False
If .Show = -1 Then xPath = .SelectedItems(1) & "\"
End With
If Len(xPath) = 0 Then Exit Sub
Set colImages = ImageFiles(xPath) 'get a Collection of image file names
If colImages.Count > 0 Then 'found some files ?
arrFiles = CollectionToArray(colImages) 'get array from Collection
SortSpecial arrFiles, "SortVal" 'sort files using `Val()`
For Each f In arrFiles 'loop the sorted array
With Selection
.Text = f
.MoveDown wdLine
.InlineShapes.AddPicture xPath & f, False, True
.InsertAfter vbCrLf
.MoveDown wdLine
End With
Next f
Else
MsgBox "No image files found in selected folder"
End If
End Sub
'return a Collection of image files given a folder location
Function ImageFiles(srcFolder As String) As Collection
Dim col As New Collection, f As String
f = Dir(srcFolder & "*.*")
Do While f <> ""
Select Case UCase(Right(f, 3))
Case "PNG", "TIF", "JPG", "GIF", "BMP"
col.Add f
End Select
f = Dir()
Loop
Set ImageFiles = col
End Function
'create and return a string array from a Collection
Function CollectionToArray(col As Collection) As String()
Dim arr() As String, i As Long
ReDim arr(1 To col.Count)
For i = 1 To col.Count
arr(i) = col(i)
Next i
CollectionToArray = arr
End Function
'Sorts an array using some specific translation defined in `func`
Sub SortSpecial(list, func As String)
Dim First As Long, Last As Long, i As Long, j As Long, tmp, arrComp()
First = LBound(list)
Last = UBound(list)
'fill the "compare array...
ReDim arrComp(First To Last)
For i = First To Last
arrComp(i) = Application.Run(func, list(i))
Next i
'now sort by comparing on `arrComp` not `list`
For i = First To Last - 1
For j = i + 1 To Last
If arrComp(i) > arrComp(j) Then
tmp = arrComp(j) 'swap positions in the "comparison" array
arrComp(j) = arrComp(i)
arrComp(i) = tmp
tmp = list(j) '...and in the original array
list(j) = list(i)
list(i) = tmp
End If
Next j
Next i
End Sub
'a function to allow comparing values based on the initial numeric part...
Function SortVal(v)
SortVal = Val(v) ' "1 day" --> 1, "11 days" --> 11 etc
End Function
So I did a very simple loop VBA to consolidate data from different workbook into single workbook. I got the out of range error keep promting me and I've tried my best to think but it's a dead end for me. Appreciate if can get some input from the seniors.
Sub consolidate()
Application.ScreenUpdating = False
Set mb = ThisWorkbook
myfdr = ThisWorkbook.Path
fname = Dir(myfdr & "\*.csv")
Do Until fname = Empty
If fname <> mb.Name Then
Set wb = Workbooks.Open(myfdr & "\" & fname)
mg = Range("A1").End(xlDown).Row
Range("M4").Value = mg
wb.Worksheets.Copy After:=mb.Sheets(mb.Sheets.Count)
wb.Close SaveChanges:=False
n = n + 1
End If
fname = Dir
Loop
Application.ScreenUpdating = True
MsgBox n & "Done"
End Sub
Sub Union()
Application.ScreenUpdating = False
Set ms = Worksheets("Sheet1")
fsn = 1
k = 0
Set mb = ThisWorkbook
myfdr = ThisWorkbook.Path
fname = Dir(myfdr & "\*.csv")
Do Until fname = Empty
If fname <> mb.Name Then
sn = Mid(fname, 1, Len(fname) - 4)
Set cs = Worksheets(sn) '<<<<The subscript out of range error happened here
If fsn = 1 Then
fsn = 0
For g = 1 To cs.Cells(4, 13)
k = k + 1
For r = 1 To 10
ms.Cells(k, r) = cs.Cells(g, r)
Next r
Next g
Else
For g = 9 To cs.Cells(4, 13)
k = k + 1
For r = 1 To 10
ms.Cells(k, r) = cs.Cells(g, r)
Next r
Next g
End If
End If
fname = Dir
Loop
End Sub
I have 2 tables as shown below
Table 1
AA
BB
CC
DD
EE
Table 2
bb
aa
bb1
bb2
cc1
cc2
cc3
I need help to do the below steps using Excel VBA code
Use Table 1 and loop thru each data in table 1 and compare to Table 2
If table 2 only have 1 match, just replace the Table 1 data from the table 2 value on the same row of data from table 1
If have multiple match from table 2, them prompt user to select which data from table 2 need to be written in table 1
Matching Criteria are as follows
AA should match to aa,aa1,aa2,,,,,,
BB shoud match bb,bb1,bb2,,,,,,,,
Below is the code that I have written
Private Sub CommandButton2_Click()
Dim attr1 As Range, data1 As Range
Dim item1, item2, item3, lastRow, lastRow2
Dim UsrInput, UsrInput2 As Variant
Dim Cnt As Integer, LineCnt As Integer
Dim MatchData(1 To 9000) As String
Dim i As Integer, n As Integer, j As Integer, p As Integer
Dim counter1 As Integer, counter2 As Integer
Dim match1(1 To 500) As Integer
Dim matchstr1(1 To 500) As String
Dim tmpstr1(1 To 500) As String
Dim storestr(1 To 500) As String
Dim tmpholderstr As String
counter1 = 1
counter2 = 0
j = 0
p = 0
tmpholderstr = ""
For i = 1 To 500
storestr(i) = ""
Next i
For i = 1 To 500
tmpstr1(i) = ""
Next i
For i = 1 To 500
matchstr1(i) = ""
Next i
For i = 1 To 500
match1(i) = 0
Next i
For i = 1 To 9000
MatchData(i) = ""
Next i
UsrInput = InputBox("Enter Atribute Column")
UsrInput2 = InputBox("Enter Column Alphabet to compare")
With ActiveSheet
lastRow = .Cells(.Rows.Count, UsrInput).End(xlUp).Row
'MsgBox lastRow
End With
With ActiveSheet
lastRow2 = .Cells(.Rows.Count, UsrInput2).End(xlUp).Row
'MsgBox lastRow
End With
Set attr1 = Range(UsrInput & "2:" & UsrInput & lastRow)
Set data1 = Range(UsrInput2 & "2:" & UsrInput2 & lastRow2)
'Debug.Print lastRow
'Debug.Print lastRow2
For Each item1 In attr1
item1.Value = Replace(item1.Value, " ", "")
Next item1
For Each item1 In attr1
If item1.Value = "" Then Exit For
counter1 = counter1 + 1
item1.Value = "*" & item1.Value & "*"
For Each item2 In data1
If item2 = "" Then Exit For
If item2 Like item1.Value Then
counter2 = counter2 + 1
match1(counter2) = counter1
matchstr1(counter2) = item2.Value
tmpstr1(counter2) = item1.Value
Debug.Print item1.Row
Debug.Print "match1[" & counter2; "] = " & match1(counter2)
Debug.Print "matchstr1[" & counter2; "] = " & matchstr1(counter2)
Debug.Print "tmpstr1[" & counter2; "] = " & tmpstr1(counter2)
End If
Next item2
Next item1
' Below is the code that go thru the array and try to write to table 1
' But it is not working as expected.
For n = 1 To 500
If matchstr1(n) = "" Then Exit For
If match1(n) <> match1(n + 1) Then
Range("K" & match1(n)) = matchstr1(n)
Else
i = 0
For j = n To 300
If matchstr1(j) = "" Then Exit For
i = i + 1
If match1(j) = match1(j + 1) Then
tmpstr1(i) = matchstr1(j)
End If
Next j
End If
Next n
End Sub
Try the following. Your two tables are suppose to be in a sheet named "MyData", where there is also a command button (CommandButton2). Add also a UserForm (UserForm1), and in that UserForm add another command button (CommandButton1).
In the module associated with CommandButton2, copy the following code:
Public vMyReplacementArray() As Variant
Public iNumberOfItems As Integer
Public vUsrInput As Variant, vUsrInput2 As Variant
Public lLastRow As Long, lLastRow2 As Long
Public rAttr1 As Range, rData1 As Range, rItem1 As Range, rItem2 As Range
Public iCounter1 As Integer
Sub Button2_Click()
vUsrInput = InputBox("Enter Atribute Column")
vUsrInput2 = InputBox("Enter Column Alphabet to compare")
With ActiveSheet
lLastRow = .Cells(.Rows.Count, vUsrInput).End(xlUp).Row
End With
With ActiveSheet
lLastRow2 = .Cells(.Rows.Count, vUsrInput2).End(xlUp).Row
End With
Set rAttr1 = Range(vUsrInput & "2:" & vUsrInput & lLastRow)
Set rData1 = Range(vUsrInput2 & "2:" & vUsrInput2 & lLastRow2)
ReDim vMyReplacementArray(1 To 1) As Variant
For Each rItem1 In rAttr1
For Each rItem2 In rData1
If (InStr(1, rItem2, rItem1, vbTextCompare)) > 0 Then
vMyReplacementArray(UBound(vMyReplacementArray)) = rItem1.Value & "-" & rItem2.Value
ReDim Preserve vMyReplacementArray(1 To UBound(vMyReplacementArray) + 1) As Variant
End If
Next rItem2
Next rItem1
iNumberOfItems = UBound(vMyReplacementArray) - LBound(vMyReplacementArray)
UserForm1.Show
End Sub
And in the Userform, the following:
Dim k As Integer
Private Sub UserForm_initialize()
Dim myElements() As String
Dim theLabel As Object
Dim rad As Object
Class1 = ""
k = 1
For i = 1 To iNumberOfItems
myElements = Split(vMyReplacementArray(i), "-")
If myElements(0) <> Class1 Then
Set theLabel = UserForm1.Controls.Add("Forms.Label.1", "Test" & i, True)
theLabel.Caption = myElements(0)
theLabel.Left = 80 * k
theLabel.Width = 20
theLabel.Top = 10
k = k + 1
j = 1
End If
Set rad = UserForm1.Controls.Add("Forms.OptionButton.1", "radio" & j, True)
If j = 1 Then
rad.Value = True
End If
rad.Caption = myElements(1)
rad.Left = 80 * (k - 1)
rad.Width = 60
rad.GroupName = k - 1
rad.Top = 50 + 20 * j
j = j + 1
Class1 = myElements(0)
Next i
End Sub
Private Sub CommandButton1_Click()
Dim ctrl As MSForms.Control
Dim dict(5, 1)
Dim i
'## Iterate the controls, and associates the GroupName to the Button.Name that's true.
i = 0
For Each ctrl In Me.Controls
If TypeName(ctrl) = "OptionButton" Then
If ctrl.Value = True Then
dict(i, 0) = ctrl.GroupName
dict(i, 1) = ctrl.Caption
i = i + 1
End If
End If
Next
'For i = 0 To k
'MsgBox "grupo: " & dict(i, 0) & "elem: " & dict(i, 1)
'Next
j = 0
For i = 1 To iNumberOfItems
myElements = Split(vMyReplacementArray(i), "-")
For Each rItem1 In rAttr1
If rItem1 = myElements(0) Then
rItem1 = dict(j, 1)
j = j + 1
End If
Next
Next i
End Sub
The following code is supposed to copy information from xlsx files(inside subfolders) and consolidate(paste) everything in a single file:
Dim xlApp, xlApp1, xlApp2 As Excel.Application
Dim xlWorkBook, xlWorkBook1, xlWorkBook2 As Excel.Workbook
Dim xlWorkSheet, xlWorkSheet1, xlWorkSheet2 As Excel.Worksheet
Dim folder, m, n As String
Dim subfolders As String()
Dim i, j, c, k, l, lastrow As Integer
Dim fec As Date
folder = My.Application.Info.DirectoryPath
ChDir(CurDir())
subfolders = IO.Directory.GetDirectories(CurDir())
xlApp = New Excel.ApplicationClass
xlApp2 = New Excel.ApplicationClass
xlApp1 = New Excel.ApplicationClass
Try
xlWorkBook = xlApp.Workbooks.Open("\\excel1.xlsx")
xlWorkSheet = xlWorkBook.Worksheets("SheetName")
xlWorkBook2 = xlApp2.Workbooks.Open("\\excel2.xlsx")
xlWorkSheet2 = xlWorkBook2.Worksheets("SheetName")
i = 2
For Each f1 In subfolders
ChDir(f1)
m = Dir("*.xlsx")
Do While m <> ""
j = 1
Do While xlWorkSheet2.Cells(j, 1).Value <> ""
If xlWorkSheet2.Cells(j, 1).Value = m Then
fec = xlWorkSheet2.Cells(j, 2).value
If fec <> File.GetLastWriteTime(CurDir() & "\" & m) Then
l = 1
n = xlWorkSheet.Cells(l, 3).value()
Do While n <> ""
If Trim(xlWorkSheet.Cells(l, 3).value) = Strings.Left(Strings.Right(m, 16), 11) Then
xlWorkBook.Activate()
xlWorkSheet.Rows(l).delete()
If Trim(xlWorkSheet.Cells(l, 3).value()) <> Strings.Left(Strings.Right(m, 16), 11) Then
n = ""
End If
Else
l = l + 1
n = xlWorkSheet.Cells(l, 3).value()
End If
Loop
xlWorkBook1 = xlApp1.Workbooks.Open(CurDir() & "\" & m)
xlWorkSheet1 = xlWorkBook1.Worksheets("Test")
xlWorkSheet1.Visible = True
xlWorkSheet1.Activate()
xlWorkSheet1.Select()
If xlWorkSheet1.FilterMode = True Then
xlWorkSheet1.ShowAllData()
End If
c = 5
Do While Trim(xlWorkSheet1.Cells(c, 4).value) <> "Entity Name"
c = c + 1
Loop
c = c + 2
If xlWorkSheet1.Cells(c, 4).value <> "" Then
xlWorkSheet2.Cells(j, 2) = File.GetLastWriteTime(CurDir() & "\" & m)
lastrow = xlWorkSheet1.Cells(65536, 3).End(Excel.XlDirection.xlUp).Row
xlWorkSheet.Cells(l, 1).Insert(Excel.XlInsertShiftDirection.xlShiftDown, xlWorkSheet1.Range("a" & c.ToString, xlWorkSheet1.Cells(lastrow, 42)).Copy())
End If
xlWorkBook1.Close()
releaseObject(xlWorkBook1)
releaseObject(xlWorkSheet1)
End If
j = j + 1000
ElseIf xlWorkSheet2.Cells(j + 1, 1).Value = "" Then
k = j + 1
xlWorkSheet2.Range("A" & k.ToString).Value = m
xlWorkSheet2.Range("B" & k.ToString).Value = "01/01/2000"
End If
j = j + 1
Loop
m = Dir()
Loop
Next
xlWorkBook2.Close()
xlWorkBook.Close()
xlApp.Quit()
xlApp2.Quit()
xlApp1.Quit()
Catch ex As Exception
...
But after this line
xlWorkSheet.Cells(l, 1).Insert(Excel.XlInsertShiftDirection.xlShiftDown, xlWorkSheet1.Range("a" & c.ToString, xlWorkSheet1.Cells(lastrow, 42)).Copy())
it fails showing the error:
System.Runtime.InteropServices.COMException(0x800A03EC): Insert Method of range class failed.
Excel files are ok, with write permissions and are local.
Any ideas?
I would like to filter a Listbox created from a list of values stored in a worksheet depending on text written in a textbox contained in the same userform.
My Listbox has 4 or 5 columns (depending on OptionField selection) and I would like to search all the columns for the text written.
Example: I write "aaa" in TextField and the Listbox should return a list based on all the lines whose column 1 or 2 or 3 or 4 or 5 contain "aaa".
Below my code to refresh the list on OptionField selection (this code does not produce any error, it is just to show how I create my list):
Sub RefreshList()
Dim selcell, firstcell As String
Dim k, i As Integer
Dim r as long
i = 0
k = 0
' reads parameters from hidden worksheet
If Me.new_schl = True Then
firstcell = Cells(3, 4).Address
selcell = firstcell
Do Until IsEmpty(Range("" & selcell & "")) And i = 2
If IsEmpty(Range("" & selcell & "")) Then i = i + 1
k = k + 1
selcell = Cells(1 + k, 7).Address(0, 0)
Loop
k = k - 1
selcell = Cells(1 + k, 7).Address(0, 0)
With Me.ListBox1
.ColumnCount = 4
.ColumnWidths = "50; 80; 160; 40"
.RowSource = ""
Set MyData = Range("" & firstcell & ":" & selcell & "")
.List = MyData.Cells.Value
For r = .ListCount - 1 To 0 Step -1
If .List(r, 3) = "" Or .List(r, 3) = "0" Then
.RemoveItem r
End If
Next r
End With
Else
firstcell = Cells(3, 11).Address
selcell = firstcell
Do Until IsEmpty(Range("" & selcell & "")) And i = 11
If IsEmpty(Range("" & selcell & "")) Then i = i + 1
k = k + 1
selcell = Cells(1 + k, 15).Address(0, 0)
Loop
k = k - 1
selcell = Cells(1 + k, 15).Address(0, 0)
With Me.ListBox1
.ColumnCount = 5
.ColumnWidths = "40; 40; 160; 40; 40"
.RowSource = ""
Set MyData = Range("" & firstcell & ":" & selcell & "")
.List = MyData.Cells.Value
For r = .ListCount - 1 To 0 Step -1
If .List(r, 3) = "" Or .List(r, 3) = "0" Then
.RemoveItem r
End If
Next r
End With
End If
End Sub
Finally I could come out with something!
Sub Filter_Change()
Dim i As Long
Dim Str As String
Str = Me.Filter.Text
Me.RefreshList
If Not Str = "" Then
With Me.ListBox1
For i = .ListCount - 1 To 0 Step -1
If InStr(1, LCase(.List(i, 0)), LCase(Str)) = 0 And InStr(1, LCase(.List(i, 1)), LCase(Str)) = 0 And _
InStr(1, LCase(.List(i, 2)), LCase(Str)) = 0 And InStr(1, LCase(.List(i, 3)), LCase(Str)) = 0 Then
.RemoveItem i
End If
Next i
End With
End If
End Sub
I know, the answer is couple of years old...
But I thought I'd share solution that works the best for me, because the filter is blazing fast even when there are thousands of items in the list. It is not without a "catch", though:
it uses a Dictionary object
Option Explicit
Dim myDictionary As Scripting.Dictionary
Private Sub fillListbox()
Dim iii As Integer
Set myDictionary = New Scripting.Dictionary
' this, here, is just a "draft" of a possible loop
' for filling in the dictionary
For iii = 1 To RANGE_END
If Not myDictionary.Exists(UNIQUE_VALUE) Then
myDictionary.Add INDEX, VALUE
End If
Next
myListbox.List = myDictionary .Items
End Sub
Private Sub textboxSearch_Change()
Dim Keys As Variant
Keys = myDictionary .Items
myListbox.List = Filter(Keys, textboxSearch.Text, True, vbTextCompare)
End Sub
Private Sub UserForm_Initialize()
Call fillListbox
End Sub