How to plot a chart with known column index in vba - excel

I am trying to create a simple userform to plot graphs of selected columns.
What I did so far is shown in the code below:
Public Sub UserForm_Initialize()
Dim Axis As Variant
Dim Axis1 As Variant
Axis = Rows(1).Value
' here I'm filling the Comboboxes with all the names in the 1st row
ComboBox1.Column = Axis
ComboBox2.Column = Axis
End Sub
Public Sub Plot_Click()
With Range("A1:ZZ1")
'Here I'm searching for the column index of the selected value in the first Combobox
Set rFind1 = .Find(What:=ComboBox1.Value, LookAt:=xlWhole, _
MatchCase:=False, SearchFormat:=False)
End With
Spalte1 = rFind1.Column
With Range("A1:ZZ1")
'Here I'm searching for the column index of the selected value in the second Combobox
Set rFind2 = .Find(What:=ComboBox2.Value, LookAt:=xlWhole, _
MatchCase:=False, SearchFormat:=False)
End With
Spalte2 = rFind2.Column
'somewhere here, I would like to plot a graph with the selected
'column indexes (Spalte1 and Spalte2)
End Sub
Private Sub Schliessen_Click()
'here I'm closing the userform
Unload Me
End Sub
The graph should look like this:
And in the future, I will also add some more Comboboxes in order to select more axis to plot
I appreciate every single answer/help and suggestion

The way, you are initializing the ComboBox will add many blank items which will become cumbersome while selecting required value. I will suggest to add only required columns instead.
Searching the selected column index again and again is also meaningless. You can use .ListIndex property to get 0 based index value. Hence the actual column index will be ComboBox1.ListIndex + 1 in case.
As you may require to add more ComboBox in future, I would rather suggest to use two ListBoxes, first with all column names and second will get updated with require columns to be used as series using Add, Remove buttons as following screenshot:

Related

When I add a row in Excel to copy the previous row's formatting, can I also copy the form control checkboxes?

I have a table with checkboxes in certain columns (see sample table)-- they are linked to their cells and also move/size with the cells. I also added text box "headings" throughout the table so visually when you filter for checked boxes, you see under which heading the checked item is in (I know I could create a separate column for that, but it works if I add text to the cells underneath the heading that I keep checked when filtering).
I want to be able to add rows at the end of each section, or before the next heading, since the formatting changes slightly in each section. However, I also want to add the checkboxes, and my code currently doesn't do that. It's okay if they're not linked to the new cell-- I have another macro I can run to do that.
Here's what my code would look like in the sample table:
Sub Add_Row_Pepperoni()
Rows(7).Insert , xlFormatFromLeftOrAbove
End Sub
Sub Add_Row_Pineapple()
Rows(13).Insert , xlFormatFromLeftOrAbove
End Sub
And I would like to add "Next" to "Call" this code:
Sub Link_CheckBoxes()
Dim chk As CheckBox
Dim lCol As Long
lCol = 0 'number of columns to the right for link
For Each chk In ActiveSheet.CheckBoxes
With chk
.LinkedCell = _
.TopLeftCell.Offset(0, lCol).Address
End With
Next chk
End Sub
My other concern is the row I'm referencing (here rows 7 and 13) will change every time I add a row above it (I'll no longer be referencing the "header" row). Any tips?

Userform Initialise with listbox filled with array from cells

I have a userform within a userform (userform-ception) where I implement a search function for part list in Row B. Prior to searching I want to check for duplicates, which triggers a second userform when true. I am having trouble populating userform2's list box when it initialises. My logic is
If duplicate count > 1, filter by column B for that search criteria
Open second userform
From the current visible cells, grab the first 7 columns and populate a list box with this (Using visible cells as array)
However when I try to open the userform it turns out blank so I am wondering if anyone can shed some light on this.
This is in my Search Function
Dim Dupl As Integer
Dupl = Application.WorksheetFunction.CountIf(Range("B:B"), PartNumberSearch.Text)
If Dupl > 1 Then
With ActiveSheet.Range("A1:M1")
.AutoFilter Field:=2, Criteria1:=PartNumberSearch
End With
UserForm2.Show
'Exiting the sub here so that when userform 2 is used to disambiguate the part it can continue to search using PartID instead
Exit Sub
This is in my userform2_initialise() function
Private Sub UserForm2_Initialize()
DupList.ColumnWidths = "35;50;60;25;10;20;40"
'Checks last row of the list
DupRow = ActiveSheet.Range("A65536").End(xlUp).Row
'Puts all the result into the ResultsList
DupList.List = Range("A2:G" & DupRow).Value
End Sub
A sample snippet of my table
Any help is appreciated. Thanks!

Set cell vlookup value based on changing Combobox value

I have input a combobox in an Excel sheet. I want it to work so that the user who does not have access to the VBA can select a value from the dropdown and then the value in another cell will perform a vlookup on this value.
In the first instance I have inserted a box and am trying to set a cell value based on this.
Sub InsertComboBox()
#inserts dropdown box on the front page and sets the values as the list of DMA from the pipe_totals sheet
#this should be the most complete list so will not change dependant on asset
Dim arearange As Range
Set arearange = Sheets("pipe_totals").Range("a:a")
lastrowi = Application.WorksheetFunction.CountA(arearange)
Sheets("front page").Activate
With Range("f5:g5")
Set Combo = ActiveSheet.DropDowns.Add(.Left, .Top, .Width, .Height)
End With
Combo.List() = Sheets("pipe_totals").Range("A2:A" & lastrowi).Value
.Range("k9").Value = Combo.Value 'only works on current combobox value which is 0
End Sub
Is there a way I can set this so the vlookup is dynamic depending on the users selection?
In this example, just set the right combo name. It should be ok, provided that your combobox lists values from "Range("A2:A" & lastrowi)" as you mention above.
Sub "comboname"_Change()
Dim list_val As Long
list_val = Worksheets("front page").Shapes("comboname").ControlFormat.Value
Range("K9") = Worksheets("pipe_totals").Cells((list_val + 1), 1)
End Sub
Sub test()
Dim z As Shape
For Each z In Worksheets("front page").Shapes
Debug.Print z.Name
Next z
End Sub
As far as I understand, you want that everytime the combobox value changes, cell K9 will have the same value also. Is that right? If this the case, then right click on the combobox and select "Assign Macro". Then select "Create". Then inside the sub created, which should look like this:
Sub "comboname"_Change()
End Sub
You should also paste the final code line.
.Range("k9").Value = Combo.Value
Doing so, means you want that line of code executed every time the combobox value changes.

Userform to populate worksheet

I'm still very new to using VBA, so I apologize if I don't know all of the preferred terms.
I am attempting to write a userform to populate a spreadsheet allowing me to track employees PTO used. This spreadsheet is the X-axis (row 1) being the date and the Y-axis (column A) being the employee name.
The userform I've created has 5 pieces of criteria:
1) Employee Name (ComboBox1; this is a drop down of multiple rows)
2) Date of PTO (ComboBox2; this is supposed to be a drop down of multiple columns)
3) Duration of PTO (OptionButton1 is 1 Day, OptionButton2 is 0.5 Day)
4) Enter Data (CommandButton1)
5) Cancel (CommandButton2)
I've completed criterion 1 by selecting and labeling the menu on the spreadsheet.
The rest is what's kicking me.
I cannot seem to get the dates (criterion 2), while in row format, to show up in the ComboBox2 drop down. If I transpose these items into a single column, I have been able to label the group and create the drop down menu. This is problematic as I will not be able to form a grid to populate.
My OptionButton1 and OptionButton2 items are intent to be the input values (1 and 0.5). At this time, I've been unable to give them values, simply names. This input is secondary to the major issue where I cannot get the grid format to work (paragraph above this).
The tertiary problem is the combination of criterion 4 and 5. My script is failing to execute CommandButton1, though I believe it's due to my extremely basic code:
Private Sub CommandButton1_Click()
cmdOK
End Sub
CommandButton2 appears to work using this code:
Private Sub CommandButton2_Click()
cmdCancel
End Sub
My end all be all question, having described my issues, would be "Is my end goal possible?" I only intend to use Excel for this, as many people already have access to it. If this is possible, then I would ask for either help identifying my error points and correcting, or a link to a coding manual where I can attempt to learn more about the functions (this is more of a long-term situation, which doesn't quite help the issue, but I would feel okay with).
Thank you in advance for responses.
Edit:
# Seth
I've made it as far as ComboBox2 (the dates) selection. I cannot get the loop, suggested below, to access the values (1 row, 365 columns).
I tried modifying the code from Seth, but I really don't know anything about loops; I feel I most likely did not fill out a section appropriately (I'm looking at .Value <> ""):
Private Sub ComboBox2_Change()
Dim i As Long
i = 1
Do While ThisWorkbook.ActiveSheet("Breakdown").Cells("A1:NC1", i).Value <> ""
Me.ComboBox1.AddItem (ThisWorkbook.ActiveSheet("Breakdown").Cells("A1:NC1", i).Value)
i = i + 1
Loop
End Sub
Using this code, I get the error "Run-time error '438': Object doesn't support this property or method"
I'm trying to find a general guide to understanding writing a loop, though I find no reference to some of the above statements, so I'm not positive how to correct my problem. I believe it might also have something to do with the properties of the box. I can enter "Dates" (my generic term for that range as defined by highlighting and labeling as such) under RowSource, though that is not looping the rows.
# Alex D
I am also attempting the path of the second post I received; i get a runtime error when I try to use:
Private Sub UserForm_Initialize()
For i = 2 To Sheets("Breakdown").UsedRange.Columns.Count
comboDate.AddItem (Cells(1, i))
comboDate.List(comboDate.ListCount - 1, 1) = i
Next
End Sub
Possibly moving where that data is defined would make this work? In general, I have a button in the sheet (aka one selects a cell and the userform pops up), so possibly the initialize isn't necessary?
Cyril 20140127 (1700 UTC)
Ok, let's go in reverse order. To your last question, "Is my end goal possible?", the answer is "sure." I don't quite follow your reasoning, but if you prefer to use Excel, so be it. I do think, though, that this going to be a painful way of recording PTO. What if, for example, I take a week off? Do I have to fill out this form once for each day?
To continue moving in reverse, your buttons need to do something. It's unclear from what you've posted if cmdCancel and cmdOK are subs that you've defined elsewhere so let's pretend they aren't. In your Cancel button you need to do one basic thing, close the form. That should be as simple as this, Unload Me.
Your OK button is the crucial piece of your macro. It's where you stitch together the values the user has entered. It's also where you do something with your option buttons. You don't actually assign values to the option buttons, you check their Value properties. So, when you users click OK the code that runs will have something in it like this:
If OptionButton1.Value = True Then
'Put 1 in the cell.
Else
'Put .5 in the cell.
End if
Note that there's no need to explicitly check OptionButton2, since you only have two choices.
Finally, the dates. It sounds like the dates are already in your spreadsheet, in some particular row. What you need to do here is loop through the cells in that row and pull the values into the list of the combo box. This should get you started. Put it the UserForm_Activate form event:
Dim i As Long
i = 1
Do While ThisWorkbook.ActiveSheet.Cells(DateRow, i).Value <> ""
Me.ComboBox1.AddItem (ThisWorkbook.ActiveSheet.Cells(DateRow, i).Value)
i = i + 1
Loop
Now we return to the OK button. You need to get the selection that was made in the date combo box. To do that you need to read the ListIndex property of the combo box and add one to it. (Adding 1 accounts for the fact that the list in the combo box starts 0, not 1.) The number that is the returned will be the column in which you insert your data.
The complete code for the OK button would be something like:
Dim Col As Long
Dim Row As Long
Dim PTOValue As Long
Col = DateComboBox.ListIndex + 1
Row = EmployeeNameComboBox.ListIndex + 1
If FullDayComboBox.Value = True Then
PTOValue = 1
Else
PTOValue = .5
End if
ThisWorkbook.ActiveSheet.Cells(DateRow, i).Value = PTOValue
Hopefully this will get you started.
Fills your criterion, and should be understandable. Assumes names start in cell(2,1) and Dates in cell(1,2). You might have to change some of the names of the elements depending on what you have. But I fully built something like you described and it works perfectly.
It does need some data validation to prevent errors, but you should be able to handle that.
'Ok button which sets the values
Private Sub CommandButton1_Click()
Columns("A:A").Select
If OptionButton1.Value = True Then
Cells(Get_Name_Row(comboName.Text), Get_Date_Column(comboDate.Text)).Value = 1
Else
Cells(Get_Name_Row(comboName.Text), Get_Date_Column(comboDate.Text)).Value = 0.5
End If
End Sub
'Cancel Button
Private Sub CommandButton2_Click()
Unload Me
End Sub
'This loads the dates into your comboBox, make sure to update its name
'I assume you use RowSource for your names, so those should be fine
Private Sub UserForm_Initialize()
For i = 2 To Sheets("Sheet1").UsedRange.Columns.Count
comboDate.AddItem (Cells(1, i))
comboDate.List(comboDate.ListCount - 1, 1) = i
Next
End Sub
'Gets what row the name is from
Public Function Get_Name_Row(SearchString As String) As Integer
Dim Rng As Range
If Trim(SearchString) <> "" Then
With Sheets("Sheet1").Range("A:A")
Set Rng = .Find(What:=SearchString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Get_Name_Row = CInt(Rng.Row)
End If
End With
End If
End Function
'Gets what column the date is from
Public Function Get_Date_Column(SearchString As String) As Integer
Dim Rng As Range
If Trim(SearchString) <> "" Then
With Sheets("Sheet1").Range("A1").EntireRow
Set Rng = .Find(What:=SearchString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Get_Date_Column = (Rng.Column)
End If
End With
End If
End Function

Importing Values based on Date: Excel Macro

I am attempting to write a fairly intelligent macro for Excel. In this instance, I have two seperate workbooks that I am transferring information between. The first workbook has a listing of dates in column A followed by corresponding values in the following columns. Like so:
As you can see, the dates and values are not consistently entered. They are only available certain days. The current entries stop at the end of 2012. The point of this macro is to add new numbers each month.
an excerpt from Workbook 2 looks like this:
My current macro currently locates the correct values in workbook 2 and copies them to Workbook 1.
Which is great except for the possibility of inconsistent dates. Where there could be 15 days worth of values in the "CMP (3 YEARS)"section, but only 14 days worth in the "CMP (4 YEARS)" section. If I were to blindly copy those values over to sheet one they would not line up correctly. I would rather there be a calculated average if a date is missing
So to remedy this problem, I am attempting the current solution:
'Grab 1 Month
Call Import("CMA/FIXED (4 WEEKS)", "B1", DestinationWorkbook, ExportedWorkbook, 3, 2, False, DestinationDateRange)
The above method is called for each column of numbers to be located as well as for extracting the dates.
Allow me to explain what is supposed to be happening below. First the String to search for in the second sheet is passed in. this is used in conjunction with the x and y offset integers to locate the correct values. The DestinationSheetName is Workbook1 and ExportedDataSheetName is Workbook2. the isDateImport boolean is there to tell the method that this is the first import and all we are grabbing is the first set of dates that will be added to column A of Workbook1. The ByRef DateRange is a pointer to those dates after they have been copied and pasted to column A of Workbook1. So obviously when this is used for dates initially this is null.
from there we check to see what kind of import we are doing. If it is for dates we just do a simple locate, copy and past. If not, we attempt an inteligent import of the located values. The idea is to create a pointer to both sets of dates, The dates in Column A in workbook1 and the dates that correspond to the values we are copying. We want the paste location to be in the correct row for each date. I create both pointers and point them at the start of both date columns. In place of the copy paste code I am just printing to the debug window. if the pointers values match each other. After comparing the dates I attempt to increment the pointers to the next values in the columns of dates.
This works great for 2 dates and then I get an error when I try to increment the pointers.
What should I be doing to fix this error? or is there an easier way to do this?... I know pointers are a little overkill for Excel spreadsheets...
Sub Import(SearchString As String, PasteLocation As String _
, DestinationSheetName As Variant _
, ExportedDataSheetName As Variant, xOffset As Integer, yOffset As Integer _
, isDateImport As Boolean, ByRef DateRange)
Windows(DestinationSheetName).Activate
Set newSpot = Range(PasteLocation).End(xlDown)
newSpot.Select 'remove
Set newSpot = newSpot.Item(2, 1)
Windows(ExportedDataSheetName).Activate
Cells.Find(What:=SearchString, After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Select
If Not isDateImport Then
'intelligent import
Set datesColumn = ActiveCell.Item(xOffset, yOffset)
datesColumn.Select 'remove
Set valuesColumn = datesColumn.Item(1, 2)
valuesColumn.Select 'remove
Set datesColumn = Range(datesColumn, datesColumn.End(xlDown))
datesColumn.Select 'remove
Set valuesColumn = Range(valuesColumn, valuesColumn.End(xlDown))
valuesColumn.Select 'remove
Set DateColumnPointer = datesColumn.Item(1, 1)
DateColumnPointer.Select 'remove
Set DateRangePointer = DateRange.Item(1, 1)
Windows(DestinationSheetName).Activate
DateRangePointer.Select 'remove
For Each cell In valuesColumn
If (DateColumnPointer = DateRangePointer) Then
Debug.Print "Same"
Else
Debug.Print "Different"
End If
'increment Pointers
Windows(ExportedDataSheetName).Activate
DateColumnPointer = DateColumnPointer.Item(2, 1)
Windows(DestinationSheetName).Activate
DateRangePointer = DateRangePointer.Item(2, 1)
Next
Else
'primitive import
Set cell1 = ActiveCell.Item(xOffset, yOffset)
If isDateImport Then
Set cell2 = cell1.End(xlDown)
Else
Set cell2 = cell1.End(xlDown).End(xlToRight)
End If
Set rng = Range(cell1, cell2)
rng.Select
rng.Copy
Windows(DestinationSheetName).Activate
If isDateImport Then
Range("W1").Select
Else
Range("V1").Select
End If
ActiveSheet.Paste
'Add grabbed values
Set numbers = Range(Range("W1"), Range("W1").End(xlDown))
numbers.Copy
newSpot.PasteSpecial xlValues
End If
Windows(ExportedDataSheetName).Activate
Range("A1").Select
End Sub
You'll need to use set in your increment pointers section to increase the range incrementally otherwise your only copying the values from the next cell up to the current one.
'increment Pointers
Windows(ExportedDataSheetName).Activate
Set DateColumnPointer = DateColumnPointer.Item(2, 1)
Windows(DestinationSheetName).Activate
Set DateRangePointer = DateRangePointer.Item(2, 1)
Unless I've missed the point of your question?

Resources