How would I go about creating dynamic Commandbutton references? i.e. change
MANAGER.CommandButton01.Caption = Sheets("DATA").Range("C" & Rows)
(which works perfectly, but only on one button of course) - to, for example:
MANAGER.CommandButton("0" & (Rows - 2)).Caption = Sheets("DATA").Range("C" & Rows)
(this code doesn't work, but it's what I've been playing around with)
So that the Commandbutton's caption is updated depending on which line of code was edited using the MANAGER Userform.
Rows can be double digits, so the "0" will have to be replaced with just Rows after Row 11, but I haven't gotten to that stage yet.
I think what you are looking for is the reference to the Controls of the userform.
MANAGER.Controls("CommandButton" & Format(Rows-2,"00")).Caption = Sheets("DATA").Range("C" & Rows)
Related
I need to perform a quite a lot of lookups with wildcards on the worksheet using a macro (mainly lookup for value & returning the value from another column though with proper adjustment it can be also just looking for a value with wildcard, and some lookups only as checks if the value exists in the dataset). My data can't be sorted and all the lookups are within a loop A or loops within loop A; wildcards are included mostly for condition "string begins with...". I often have to find a value in one row and find corresponding value in row N rows below or above.
I have a working code, but I wonder if it can be done faster. #response to comment about posting it on Code Review (sorry, I cannot comment yet :)) - preparation the whole code to posting would take a bit too much time for me, confidentiality etc, so I prefer to treat it as a general question to be worked on this example.
Example data (I can add more columns, if I need any helper column):
Example Data picture at Imgur
Assume 100 000 rows (max xPagesCount = 1000, typically around 400; all values for certain xPage is in one block). Due to a lot of possible rows with additional data I can't simply find one value and add numbers to the found row to find the other values by their position.
Example lookups to perform while looping through consecutive xPages (so, for each given xPage):
value in row just below row with "RESTRICTIONS:" text
find name (which is always given with height (column C) = 35)
find RSW number (which can be in several rows depending on page content, but always below name)
find all rows starting with the same four digits as RSW, in two formats: DDDD.LLL.DD and DDDD.DDDDD.DD (L letter, D digit) (I use internal loop here)
check if there is a text "MASTER" (or "MASTER " etc.)
find all values between values "DOCUMENTS:" and "OPTIONS:", which quantity can be from 1 to 50 (I use internal loop here)
I was wondering, what is the fastest way to do such lookups?
What I tried:
using a dictionary on all dataset (keys in column A or C with, values
col.D) but as dictionary can't work on wildcards, I had to add ifs
for not finding a key to perform additional Application.Match
lookup... and then realized it mostly worked on these Match lookups
and not sure I even need a dictionary. I also have duplicate values
within a page and dictionary was getting only first value, regardless
their position (for example, several attachments could have value 1).
The main use remained dict.exists("MASTER") but when I removed
dictionary and changed it to IsError(Application.Match(...)) the code
worked slightly faster.
Application.Match in whole range, typical example: Application.Match(xPage & "4???.*", sh.Range("A1:A" & LastRow), 0)
in few places I use If xValue Like "????.???.??" Then construction
I have dictionary lookups with ifs redirecting to Application.Match:
xValue = dict(xPage & "ATH.416")
If dict(xPage & "ATH.416") = "" Then xValue = Application.Match("ATH.*", Sheets(1).Range("D:D"), 0)
What I consider, but not sure it's worth the effort:
altering the code that at the beginning of the iteration I find the first and the last row for xPage, and then each later check is performed in this range
xStartPage = sh.Range("D" & Application.Match(xPage, sh.Range("A1:A" & LastRow), 0))
'or, I guess better:
xStartPage = xEndPage + 1
If xPage = xPagesCount Then
xEndPage = LastRow
Else
xEndPage = sh.Range("D" & Application.Match(xPage + 1, sh.Range("A1:A" & LastRow), 0) - 1)
End If
xValue = sh.Range("D" & Application.Match("4???.*", sh.Range("D" & xStartPage & ":D" & xEndPage), 0)).Value
I have a sheet that has a few hundred drop down boxes. I want a button that resets them all to the null or top value when clicked. I can get it to work for individual drop downs but I can't get the syntax right to loop through a group of them. I've tried everything I can think of to append "i" onto "Drop Down" but can't get it to work.
This works fine, I don't want to write this a few hundred times:
ThisWorkbook.Sheets("sheet1").Shapes("Drop Down 260").ControlFormat.Value = 1
How do I get this to work:
For i = 1 To 260
ThisWorkbook.Sheets("sheet1").Shapes("Drop Down & i").ControlFormat.Value = 1
Next i
I've tried ("Drop Down" & " " & "i"), ("Drop Down" & " " & i), and everything else I could think of. I've exhausted Google and can't figure it out.
Am creating a form in which the user will be able to select 4 checkboxes. Blue, Green, Yellow, Red. They have to do this atleast twice, up to 5 times in total.
The Form Example
The first checkboxes are on the form, the other 4 grouped checkboxes are on multipages.
I've tried giving them a group name "Reeks" to "Reeks4", to then print their values into a single cell separated by comma.
The code I've found so far does print the values neatly, however, it grabs every available checkbox on my form instead of just from the group "Reeks".
The ways I've tried to add the groupname (or tag, named them both the same) to the code, only gives me errors.
For Each Control In Me.Controls
If TypeName(Control) = "CheckBox" Then
'If Control.GroupName = "Reeks" Then
If Control.Value Then
Reeks = IIf(Reeks <> "", Reeks & ", ", "") & Control.Caption
End If
End If
Next
With ws
.Cells(iRow, 5).Value = Reeks
End With
Any help is welcome, but if at all possible please add comments as I only started on VBA last week.
(Side note. I also have framed checkboxes on the multipages in which the user can select the location of said colour. Side + Top view. Which will need to work the same as with the colours, but printed in different columns. )
I'm trying to make a report form that will ask what month and year you want the report to show. However, there is a specific pivot table that uses a four-year range to show trends data.
However, all the pivot tables on my workbook are connected through Power Pivot/Data Model. Using this source here, I was able to easily change slicers for single-items only.
An example that's working:
ActiveWorkbook.SlicerCaches("Slicer_Month2").VisibleSlicerItemsList = "[Calendar].[Month].&[" & frmGen.cbMonth.Text & "]"
But when I used a loop to replace multiple selections in the slicer, I've encountered an error after it's done looping all of the selection, with an error '28': Out of stack space.
For i = 0 To 3 Step 1
ActiveWorkbook.SlicerCaches("Slicer_Year").VisibleSlicerItemsList(i + 1) = "[Calendar].[Month].&[" & frmGen.txtYear.Text - 3 + i & "]"
Next
Since there's already four that was selected on the slicer, it should have been able to replace it, which is also shown when I added the code onto the watch window. But it always show that error after the loop, even if I lower the loop count.
Is there another way of selecting multiple items in a slicer that's connected through Power Pivot?
Thanks to Damian for providing a clue to my problem, I simply had to update one of the pivot tables that's linked to the slicer and it updated the other pivots just fine.
For i = 0 To 3 Step 1
ar(i) = "[Calendar].[Year].&[" & frmGen.txtYear.Text - 3 + i & "]"
Next
ActiveWorkbook.Sheets("pg2").PivotTables("pvtPg2_SPARK").PivotFields("[Calendar].[Year].[Year]").VisibleItemsList = ar
Very new to PQ, and I'm pretty sure it can do what I need in this situation, but I need help figuring out how to get there.
I have a timesheet report with 20 columns covering 50 rows that will need to be formatted to a word doc for uploading into a separate system. The original data in the cells range from 0 to any negative 2 digit number (ex: "-20"), but they need to be formatted to a seven-character set ending in ".00".
Examples:
0 will need to become "0000.00"
-4 will need to become "-004.00"
-25 will need to become "-025.00"
I think I should be able to use the text.insert function, but I'm not familiar enough with M Language to get it to do what I want it to do.
Any solutions/suggestions?
Here's my previous answer revisited...set up to use a function. You can just invoke the function once for each column you want to reformat. You'll just pass the name of the column you want to reformat to the function as you invoke the function each time.
Create a new blank query:
Open the new query in Advanced Editor and highlight everything in it:
Paste this over the highlighted text in the Advanced Editor:
let
FormatIt = (SourceColumn) =>
let
Base = Number.Round(SourceColumn,2)*.01,
Source = try Text.Start(Text.Range(
if Base < 7 then Text.From(Base) & "001" else
Text.From(Base),0,7),2) & Text.Range(Text.Range(
if Base < 7 then Text.From(Base) & "001" else
Text.From(Base),0,7),3,2) & "." & Text.End(Text.Range(
if Base < 7 then Text.From(Base) & "001" else
Text.From(Base),0,7),2)
otherwise "0000.00"
in
Source
in
FormatIt
...and click Done.
You'll see a new function has been created and listed in the Queries list on the left side of the screen.
Then go to your query with the columns you want to reformat (click on the name of your query that has the numbers you want to change in it, on the left side of the screen) and...
Click Invoke Custom Function
And fill out the pop-up like this:
- You can make up a different New column name than Custom.1.
- Function Query is the name of your query you are calling (the one you just created when you pasted the code)...for me, it's called Query1.
- Source Column is the column with the numbers you want to format.
...and click OK.
You can invoke this function once for each column. It will create a new formatted column for each.
You can use this formula = Text.PadStart(Text.From([Column1]),4,"0")&".00") in PQ to add new column that looks similar to your needs.
Here's an admittedly "busy" formula to do it:
= Table.AddColumn(#"Changed Type", "Custom", each Text.Start(Text.Range(if Number.Round([Column1],2)*.01 < 7 then Text.From(Number.Round([Column1],2)*.01) & "001" else Text.From(Number.Round([Column1],2)*.01),0,7),2) & Text.Range(Text.Range(if Number.Round([Column1],2)*.01 < 7 then Text.From(Number.Round([Column1],2)*.01) & "001" else Text.From(Number.Round([Column1],2)*.01),0,7),3,2) & "." & Text.End(Text.Range(if Number.Round([Column1],2)*.01 < 7 then Text.From(Number.Round([Column1],2)*.01) & "001" else Text.From(Number.Round([Column1],2)*.01),0,7),2))
It assumes your numbers that you want formatted are in Column1 to start. It creates a new column...Custom...with the formatted result.
To try it out, start with Column1 already populated and loaded into Power Query; then click the Add Column tab and then the Custom Column button, and populate the pop-up window like this:
...and click OK.
With more time, the repetitive parts could be made with variables to shorten this up a bit. This could also be turned into a function, given some time. But I don't have the time right now, so I figured I'd give you at least "something."