Exporting data from a userform output into an Excel spreadsheet - vba

I want to ask whether anyone is familiar of a way to export data from a Userform listbox into a separate Worksheet.
For example, I have stored and displayed 3 columns ("Name", "Company" and "Position") together with multiple rows in a userform listbox and I want to transfer this into an Excel worksheet(with a click of a button) with the corresponding columns and rows.
Thanks for anyone who might provide any advice!
'Display the matching results with all parameters on new row of the results list
Rownum = ResultsList.ListCount
ResultsList.AddItem
ResultsList.List(Rownum, 0) = Name.Value
ResultsList.List(Rownum, 1) = Company.Value
ResultsList.List(Rownum, 2) = Position.Value
Else
End If
End Sub
Private Sub CommandButton1_Click()
Sheets.Add = ResultsList.Value
End Sub
I am essentially trying to get the result in "ResultsList" which is working ok, into a new sheet in excel.
Sorry for not adding in earlier.

The following seems to be what you are trying to do:
Private Sub CommandButton1_Click()
Dim m As Long, n As Long
Dim ws As Worksheet
m = ResultsList.ListCount
n = ResultsList.ColumnCount
Set ws = Sheets.Add
ws.Range(ws.Cells(1, 1), ws.Cells(m, n)).Value = ResultsList.List
End Sub
The code assumes that it is a multicolumn list and might fail with a single column (I haven't tested with that). It creates a new sheet, putting the values in the new sheet starting at A1. I'm not convinced that this is actually a good idea. I tend to find VBA code which creates new worksheets without good reason somewhat annoying -- so make sure that you have a good reason to put it on a new sheet rather than somewhere on a current sheet (perhaps at a user-selected location).

Related

Not Understanding why I am receiving 'Subscript Out Of Range'

I have been working on this code in which I have a userform that has a mashup of listboxes and comboboxes. So far I have populated the listboxes but for some reason I am having trouble with the comboboxes (combobox1 and combobox2).
I have managed to populate the drop-down list for combobox1, and from that list I want to 'filter' through a named range that is already called out through the 'name manager'. The named range is called Range_Books.
Range_Books references two columns and a variable number of rows in table48 on sheet BOOKS or in VBA code Sheet7. The code below is my latest iteration of attempting to accomplish what I have explained but it still has failed.
I originally was attempting to call out the range directly without the Worksheets("Sheet7"). since the named range is not on a specific sheet, but I am still not sure which is the best way to call out the range and if that is the root of my problem. I have called out the range directly without the worksheets(" ") before which is why I am so perplexed by this.
It may be important to note that when the userform is initialized, it opens a secondary workbook in order to populate the listboxes. After initialization, various actions may be done before a value is chosen for combobox1, and thus activating the function I am trying to create. This secondary workbook stays open until the userform is closed. I mention this because I am unsure if the secondary workbook is causing issues with the range object. I have been receiving trouble from VBA since adding the opening of a secondary workbook functionality to the userform.
Private Sub ComboBox1_Change()
Dim count As Integer
Dim i As Integer
count = Worksheets("Sheet7").Range("Range_Books").Rows.count
For i = 0 To count
If Worksheets("Sheet7").Range("Range_Books").Cells(i, 1) = ComboBox1.Value Then
ComboBox2.AddItem (Worksheets("Sheet7").Range("Range_Books").Cells(i, 2))
End If
Next i
End Sub
You need to either start with For i = 1 to count, or change the ranges to .Cells(i+1,1)...
Also, make sure you're referring to the correct sheet. I think this is where the crux of your issue is.
If your named range is in a worksheet with the tab name "Books", then you need to instead use count = Worksheets("Books").Range("Range_Books").Rows.count
If you want to use the "Sheet7" reference instead, you could use count = Sheet7.Range("Range_Books").Rows.count
For i = 0 To count
...
Cells(i, 1)
at this point, i = 0. Row 0 Doesn't exist.
Change i = 0 to i = 1
Use this
Private Sub ComboBox1_Change()
Dim count As Integer
Dim i As Integer
Dim ws As WorkSheet
Set ws = Sheets("Sheet7")
count = ws.Range("Range_Books").Rows.count
For i = 1 To count
If Worksheets("Sheet7").Range("Range_Books").Cells(i, 1) = ComboBox1.Value Then
ComboBox2.AddItem (Worksheets("Sheet7").Range("Range_Books").Cells(i, 2))
End If
Next i
End Sub
Thank you everyone for the help, it is very much appreciated! My final working code is below. I changed all instances of Worksheets("Sheet7") to just Sheet7. I attached a picture of the Excel Objects folder tree, as you can see I have Sheet7 which I named "Books". My confusion was that Worksheets(" ") calls out the name I assign rather than the VBA assigned name for the sheet. I also added ComboBox2.Clear that way whenever ComboBox1 changes it resets the values rather then stacking them. I hope this helps somebody in the future and thanks again to the commentors who helped me!
enter image description here
Private Sub ComboBox1_Change()
ComboBox2.Clear
Dim count As Integer
Dim i As Integer
count = Sheet7.Range("Range_Books").Rows.count
For i = 1 To count
If Sheet7.Range("Range_Books").Cells(i, 1) = ComboBox1.Value Then
ComboBox2.AddItem (Sheet7.Range("Range_Books").Cells(i, 2))
End If
Next i
End Sub

Multi language Excel VBA Application

I basically created an Excel VBA application that manipulate Excel worksheets, so in the code, I use the string "Sheet1" to refer to the first sheet of a workbook, but when I try to use this application with the same code with a french version of Excel, it doesn't work until I translate "Sheet1" to "Feuil1". So my question is, is there a way to automatically adapt the code to any version of Excel ?
You can use the following ways to get a sheet from code:
(1) using by Sheets(sheet_index)
This way cannot be adapt because it take the sheet by sheet index (sheet index are start from 1). When sheet are change place, it cannot access the right sheet.So, it should not use.
For example: Set Feuil1Sheet = Sheets(1)
(2) using by (Name) of VBA editor
I think this way should not use never, because it takes the sheet by code name which can only visible by VBA editor(it shows as (Name) field in sheet properties). I think you are using this way for getting the first sheet. So, you not get the right sheet. One thing you need to know is that code name of every first sheet may not be Sheet1 always. It can be Sheet2 or Sheet4, etc.
For example: Set Feuil1Sheet = Sheet1
(3) using Worksheets("sheet-name") or Sheets("sheet-name")
This last way is a very compatible way and can be adapt in anywhere Excel because it take the sheet by its name. So, If names are equal, you will get the right sheet. So, use this for getting the sheet.
For example: Set Feuil1Sheet = Worksheets("Feuil1") or Set Feuil1Sheet = Sheets("Feuil1")
The only possible way I can think of to always reference "sheet1" in the local language is the following code.
Option Explicit
Public Sub GetLocalNameForNewSheets()
Dim strSheetName As String
Dim i As Long
i = ActiveWorkbook.Sheets.Count
ActiveWorkbook.Sheets.Add After:=Worksheets(i)
strSheetName = ActiveWorkbook.Worksheets(i + 1).Name
Application.DisplayAlerts = False
ActiveWorkbook.Worksheets(i + 1).Delete
Application.DisplayAlerts = True
Debug.Print strSheetName
For i = 1 To Len(strSheetName)
While IsNumeric(Mid(strSheetName, i, 1))
strSheetName = Replace(strSheetName, Mid(strSheetName, i, 1), "")
Wend
Next i
Debug.Print strSheetName
Debug.Print strSheetName & "1"
End Sub
Basically, I am asking Excel to create a new sheet and name it for me. Then, I am getting the new name which is "sheet" in the local language and remove from the string the number part. At the end, you can add the number "1" to reference the first sheet.

VBA listbox select worksheet by index

I have a form with listbox which dynamically provides a list of the worksheets in the current workbook (code below). I wish to take the selected Sheet and refer to it in a formula later in the process. From hours of playing around I cannot seem to accomplish this. I believe I read somewhere that you cannot take the string back to the sub and use it to refer to to an object. So I thought maybe I can create two listboxes
for sheet name
for sheet index
that I could pass the index number to and maybe use that in my formula to lookup items from the correct sheet.
For the life of my I cannot seem to find a way to connect the two since the items will always be changing; the code will be ran on multiple workbooks by multiple operators so the layout will most likely change between users. I can easily add the second list box with index #'s but I have a block on how to associate the name which will have meaning to the user and the index which I can pass back to the sub. I realize the "On click" procedure for the list box to associate the two but with the dynamic nature of the fields I cannot come up with the logic to put that into code.
For N = 1 To ActiveWorkbook.Sheets.Count
With ListBox1
.AddItem ActiveWorkbook.Sheets(N).Name
End With
Next N
Try this out.
Declare a public variable above the code for the UserForm, making it available throughout your workbook from any module or code.
Public listChoice As String
Using your code to get the sheet names for the ListBox rowsource.
Private Sub UserForm_Activate()
For n = 1 To ActiveWorkbook.Sheets.count
With ListBox1
.AddItem ActiveWorkbook.Sheets(n).name
End With
Next n
End Sub
Including an update event for the ListBox
Private Sub ListBox1_AfterUpdate()
listChoice = ListBox1.Text
End Sub
I included a test just to demonstrate that the result is still retained. You don't need this, it demonstrates the results on the screenshot.
Private Sub cmdTestChoice_Click()
MsgBox ("The choice made on the ListBox was: " & listChoice)
End Sub
edit: To access that sheet later, you can call it using something like this:
Some examples of different ways to access a cell, using .Range, or .Cells, with numbers or letters.
Using lRow & lCol as Long to set row and column numbers.
Sheets(listChoice).Cells(lRow, lCol).Value = TextBox1.Value 'Set cell on sheet from TextBox
TextBox2.Value = Sheets(listChoice).Range("A2").Value 'Set TextBox From Cell on Sheet
'Set a cell on another sheet using the selected sheet as a source.
Sheets("AnotherSheet").Cells(lRow, "D") = Sheets(listChoice).Range("D2")

Excel macro select two ranges and compare

This is a question that was asked to me in an interview. I have a excel list. It is copied to another location and then by mistake a row in the new location gets deleted.
Now I need to write a macro to compare the old and new ranges and then provide the missing data as result.
I can perhaps perform the comparison part. But the problem is I don't know how to get the selected range as input in a macro.
For eg. as soon as I select a range, it should be sent as input to the macro, then the macro should wait for another selection. As soon as I select the new range, the macro should compare and find the missing lines in new range.
Regarding the selection per mouse click you could look at the link I sent in the comments of the other answer. Selection_Change is an event which gets triggered when you change the selection of a worksheet (not only mouseclick but move-by-keys as well). The target coming in is the cell which you have selected. You can pass this as a range on to a function.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
showMsg Target
End Sub
Private Function showMsg(r As Range)
MsgBox r.Address
End Function
You can just as well use another event like BeforeDoubleClick or BeforeRightClick. Check out the events of Excel and choose the one you feel fits best.
If you only want the function to be triggered for a certain range you can filter it.
If target.column <> 1 then exit function
If you don't want the event to trigger your function each time you change a selection you can choose one cell to be the switch which gets triggered by the same event.
If target.address = "$A$1" Then Call toggleSearch()
with toggleSearch being the switching function.
This is a classical diff (and a simple one at that), you shouldn't select by hand or anything. Just sort the two lists in an identical way, then run a Sub which loops over the number of rows in the source sheet comparing each row with the same row in the target sheet. The first mismatch you get is the missing line.
This example assumes both sheets are in the same workbook but you can easily adapt it
Public Sub diffThem()
Dim src as Worksheet, trg as Worksheet
Dim r as Range, i as Integer
Set src = ThisWorkbook.Sheets("Source")
Set trg = ThisWorkbook.Sheets("Destination")
Set r = src.Range("A1")
For i = 1 to ThisWorkbook.Sheets("Source").UsedRange.Rows.Count
If r.EntireRow <> trg.Range("A" & r.Row).EntireRow Then
MsgBox("The missing row is " & r.Row)
Exit Sub
End if
Set r = r.Offset(1,0)
Next i
End Sub
If EntireRow cannot be run due to different layouts or whatever then loop the columns at that point.

VB Compare two range of cells in multiple workbooks and if match copy to different cell

I am trying to figure this out all day. This is what I need to accomplish:
Using GetFile select a number of workbooks without opening them.
Compare Cell A2 of selected workbooks indiviually in loop to a reference workbook.
If Cell A2 of the selected workbook equals the numerical value of the numerical value within the reference workbook contained within column A then copy/past column B's text in the corresponding cell of the matched reference workbook cell to M2 of the selected workbook.
Sounds complicated but let me demonstrate. The letters represent column names.
Selected Workbook
A2=12 M2= ""
Reference Workbook
A2=12 B2=milk, protein
Desired result:
Selected Workbook
A2=12 M2=milk, protein
So far this is the code I have:
Sub Click()
Dim rCell As Range, vVal1, vVal2
Dim wbCheck As Workbook
For Each rCell In Workbooks("2.xls").Worksheets(1).Range("A1:C100")
vVal1 = rCell
vVal2 = ThisWorkbook.Worksheets(1).Range(rCell.Address)
If IsNumeric(vVal1) And IsNumeric(vVal1) Then
If vVal1 = vVal2 Then
rCell.Interior.ColorIndex = 3
ElseIf vVal1 < > vVal2 Then
End If
End If
Next rCell
End Sub
Why do you need a VBA code for this?
This can be achieved using an Excel Formula.
Paste this in M2 and copy it down
=IF(A2='C:\[Ref.xlsx]Sheet1'!A2,'C:\[Ref.xlsx]Sheet1'!B2,"")
My Assumptions (Please change as applicable)
The reference file name is Ref.xlsx
You are pulling data from Sheet1 of reference file
The Ref.xlsx is in C:
EDIT
Even if you want to use VBA, you can also do this.
Sub Sample()
Application.Calculation = xlCalculationManual
ThisWorkbook.Sheets("Sheet1").Range("M2").Formula = _
"=IF(A2='C:\[Sample.xlsx]Sheet1'!A2,'C:\[Sample.xlsx]Sheet1'!B2,"""")"
Application.Calculation = xlCalculationAutomatic
End Sub
The above formula or code is beneficial becuase of what you mentioned in 1st point Using GetFile select a number of workbooks without opening them. If you do not want to open the file then the formula or formula in VBA is the way to go :)
I solved my own question. The answer was to use VLookup.
=VLOOKUP(I2, 'C:\Desktop\Merge[ISReference.xlsx]Reference'!B2:G1923, 6, FALSE)
I am surprised no one suggested this to me. Given its simplicity I was able to build this function into some code I built to run through a FSO filedialog picker on a form in access and link external workbooks with Vlookup.
Thanks Siddarth for giving the proper direction of embedding a function instead of crazy iterated loop.