I apologize for my English.
I want my flow in PAD to take the 'Yes' and 'No' values from a column in an Excel file And if yes, it opens the link from another column and write the value of the desired UI-element in the Excel file. If-condition and loop work well separately , but not together. Thank you for your help.
Yeah, you need to think a little differently.
I've recreated your workbook (to a degree) with the following information in the relevant cells.
When looping, you need to process one of the data tables and then get the index row from each other table from within the loop.
For example, loop over each priority and then for the given priority, get the URL in the corresponding row. Naturally, this means that both tables need be of the same size.
Bottom line though, you need to loop over each row and process each one individually. That's the main problem with your current script, it's trying to process the priorities in bulk, that won't work.
This script can be pasted into PAD and it will demonstrate the thinking you need to apply, just change the reference to the workbook and the columns, etc. ...
Excel.LaunchAndOpen Path: $'''c:\\temp\\Data.xlsx''' Visible: True ReadOnly: False LoadAddInsAndMacros: False Instance=> ExcelInstance
SET RowIndex TO 0
Excel.ReadCells Instance: ExcelInstance StartColumn: $'''A''' StartRow: 1 EndColumn: $'''A''' EndRow: 11 ReadAsText: False FirstLineIsHeader: True RangeValue=> URLs
Excel.ReadCells Instance: ExcelInstance StartColumn: $'''B''' StartRow: 1 EndColumn: $'''B''' EndRow: 11 ReadAsText: False FirstLineIsHeader: True RangeValue=> Priorities
LOOP FOREACH Priority IN Priorities
SET URL TO URLs[RowIndex]
IF Priority = $'''Y''' THEN
Display.ShowMessage Title: $'''URL''' Message: URL Icon: Display.Icon.None Buttons: Display.Buttons.OK DefaultButton: Display.DefaultButton.Button1 IsTopMost: False ButtonPressed=> ButtonPressed
END
Variables.IncreaseVariable Value: RowIndex IncrementValue: 1 IncreasedValue=> RowIndex
END
Excel.Close Instance: ExcelInstance
You can see I have a variable called RowIndex that I increment each time. That variable provides a link to the other data table by giving me the position of the current and allows me to get the URL for the given row.
That's one solution.
Alternatively, you could pull back all columns between AD and AG and then simply reference the column on each row as you loop around.
Related
I wrote a VBA script/macro which runs when a change is detected in a specific range (n x m) of cells. Then, it changes the values in another range (n x 1) based on what is detected in the first range.
This bit works perfectly ... but then comes the age old erased undo stack problem. Unfortunately, the ability for the user to undo their last ~10 or so actions is required.
My understanding is that the undo stack is only cleared when VBA directly edits something on the sheet - but it is preserved if the VBA is just running in the back without editing the sheet.
So my question is: Is it possible to use an in cell formula (something like below) to pull values from a VBA array?
'sample of in-cell function in cell A3
=function_to_get_value_from_vba_array(vba_array, index_of_desired_value)
Essentially, VBA would store a 1D array of strings with the values needed for the range. And by using a formula to grab the value from the array: I might be able to get around the issue of the undo stack being erased.
Thanks!
Solution
You need to do something like the following: your argument for the function should be calling the array bulding; I created one dummy function that creates some sample arrays to demonstrate it. In your case, likely you will need to store the changes on the worksheet event in a global array variable instead, and as you stated, do nothing on the worksheet (whenever a change happens, just redim or appended it on your global array as needed). However, a new problem may arise and that is when you close/reopen, or by some reason the array is lost, so you need to keep track of it, I would suggest to catch before close event and then convert the formulas to static values.
Function vba_array(TxtCase As String)
Dim ArrDummy(1) As Variant
Select Case TxtCase
Case "Txt": ArrDummy(0) = "Hi": ArrDummy(1) = "Hey"
Case "Long": ArrDummy(0) = 0: ArrDummy(1) = 1
Case "Boolean": ArrDummy(0) = True: ArrDummy(1) = False
End Select
vba_array = ArrDummy
End Function
In your calling function, do the following
Function get_value_from_vba_array(vba_array() As Variant, index_of_desired_value As Long) As Variant
'when parsing, even with option base 0 it starts at 1, so we need to add 1 up
get_value_from_vba_array = vba_array(index_of_desired_value + 1)
End Function
In your book, your formula should be something like:
=get_value_from_vba_array(vba_array("Txt"),1)
Demo
I did some actions before, so you are able to see that the "undo" works
I think I am missing something obvious but have been looking at it for so long I think I may be blind to it.
I have a sheet coded to create a pivot table from a downloaded report and apply specific filters to the pivot table - which I am aware will have some instances where there is only 1 item in the filter list so cannot apply and returns an error.
I have managed to add 'On Error GoTo...' a line past the code I know will not be able to process.
However, I also have a second Pivot Table on the same sheet which applies the same filter but in reverse - i.e. the filter will usually have 2 items, so the 2 pivot tables end up showing the breakdown of the contents of each item.
The problem is 'On Error GoTo...' is not working on the second item.
I have the GoTo locations name differently - the first pivot GoTo = 'NoOKL:' and the second = 'NoOKS:'.
Because an error on the first Pivot will mean an error on the second every time I am trying to get around this by adding 'P = 1' to the error handling of the first Pivot and then added the code below for the second:
If P = 1 Then GoTo NoOKS
With ActiveSheet.PivotTables("PivotTable11").PivotFields("CATEGORY")
.PivotItems("OKL_CONTRACTS").Visible = False
End With
ActiveSheet.PivotTables("PivotTable11").PivotFields("CATEGORY"). _
EnableMultiplePageItems = True
NoOKS:
End If
I have tried moving the GoTo location 'NoOKS' both inside the If statement and outside but get the same result.
Any help would be appreciated.
Here's an example of what your code might look like if you omit all GoTo's.
If P = 1 Then
With ActiveSheet.PivotTables("PivotTable12").PivotFields("CATEGORY")
.PivotItems("OKL_CONTRACTS").Visible = False
.EnableMultiplePageItems = False
End With
Else
With ActiveSheet.PivotTables("PivotTable11").PivotFields("CATEGORY")
.PivotItems("OKL_CONTRACTS").Visible = False
.EnableMultiplePageItems = True
End With
End If
This code presumes that you have 2 pivot tables of which you want to hide one subject to the number of items it will display (presumed to be P) and set the EnableMultiplePageItems property differently. This doesn't make much sense in the above example but the objective is to show the use of If and Else instead of GoTo.
I point out that EnableMultiplePageItems = (P = 1) would also set the property to either True or False depending upon the evaluation of the statement (P = 1). In the above example the property belongs to different objects but if you have to set the same property for the same object to different values in your project depending upon the value of P that method will avoid even the use of If, not to mention GoTo and reduce the amount of code as well.
it's me again - I'll get to know this language better eventually.
Basically - I have a big table of data that has autofilter on - range "$B$5:$Z$1697"
However, there is an additional filter on the R column that I want to be toggled on or off.
Therefore I need an If statement that says when the additional filter is on, remove, whereas, if the filter is not on at the time you press the button - apply it.
I've played around with this and watched more videos that I care to admit. However, there must be something I'm overlooking or don't understand.
The code works up until the Else line, which returns:
"Compile Error, Syntax Error".
Can anyone explain what's happening?
If Sheets(4).Range("$B$5:$Z$1697").AutoFilter(Field:=17, Criteria1:="=") = True Then
'If there specific filter on column R is on then
Sheets(4).Range("$B$5:$Z$1697").AutoFilter Field:=17
'Turn off that filter.
Else: Sheets(4).Range("$B$5:$Z$1697").AutoFilter(Field:=17, Criteria1:="=")
'Else, if the filter is off, turn it on.
End If
End Sub
EDIT: I have corrected the code, amending this ELSE line to this
Else: Sheets(4).Range("$B$5:$Z$1697").AutoFilter(Field:=17, Criteria1:="=") = True
However, when I run this now it means that it turns the filter On and then Off again with one push of the button. How do I make it so it onl makes on change at a time.
I.e. if the filter is on when the button is pressed it ONLY turns it off.
And vice versa
The easiest way to toggle a filter on/off is to use an ActiveX Toggle button. When the toggle button is clicked (enabled) your filter will be applied, when clicked again (disabled) your filter is removed. Change the name of the toggle button and Criteria1 to meets your needs.
Private Sub ToggleButton1_Click()
'when selected(enabled) the filter for Col "Q" will be enabled
If ToggleButton1.Value = True Then
Sheets(4).Range("$B$5:$Z$1697").AutoFilter Field:=17, Criteria1:="2"
Else
'when selected again(disabled) the filter for Col "Q" will be Disabled
Sheets(4).Range("$B$5:$Z$1697").AutoFilter Field:=17
End If
End Sub
This is NOT a complete answer, but I can't fit all this into a comment...
I've found that continually using compound references to refer to different objects within Excel can really give me headaches. Using intermediate objects doesn't impose any significant performance penalty at all, so I am in the habit of breaking down the compound reference into a series of intermediate objects. Doing this gives me at least two advantages: 1) I can examine the intermediate objects to make sure of the data I think should be there, and 2) I get far fewer syntax errors because each step gets validated.
So, while I can't check if this is correct since I can't access your data, your logic could look like this
Sub Example()
Dim fourthWS As Worksheet
Dim filteredData As Range
Set fourthWS = ThisWorkbook.Sheets(4)
Set filteredData = fourthWS.Range("$B$5:$Z$1697")
Dim dataIsFiltered As Variant
dataIsFiltered = filteredData.AutoFilter(Field:=17, Criteria1:="=")
If dataIsFiltered Then
'--- turn off the filter
filteredData.AutoFilter Field:=17
Else
'--- turn on the filter
filteredData.AutoFilter Field:=17, Criteria1:="="
End If
End Sub
I am trying to hide and unhide series in a chart based on their name using excel vba and I have a error 1004 invalid parameter after the first run of the for cycle.
Sub macroChart3()
'
' macroChart3 Macro test
'
Dim i, n As Integer
For i = 1 To 96 Step 1
If ActiveChart.SeriesCollection(i).Name = "*contracted*" Then
ActiveChart.SeriesCollection(i).IsFiltered = False
Else
ActiveChart.SeriesCollection(i).IsFiltered = True
End If
Next i
End Sub
SeriesCollection.IsFiltered method seemed to toggle this check box:
I couldn't use that. I wanted to record macro and see if any other method is used but the checkbox is gone in 2010:
So it might be not possible to use that anymore. If you are using a different version where this method exists you might have a problem that the series is not listed in in seriesCollection anymore:
Remarks from MSDN
When a user filters out a series, the series IsFiltered property switches to True, and the series is transferred out of its parent SeriesCollection.
See if you can use FullSeriesCollection instead when you change the visibility of series:
ActiveChart.FullSeriesCollection(2).IsFiltered = True
If that doesn't work you might add and remove ranges instead of hiding them.
UPDATE:
Run your macro in step mode (F8) so you have full visibility of the execution steps. Add your evaluated expressions (ones that are used within IFs) to see their result and you will find out if they are incorrect or are evaluated as FALSE and try to figure out why.
And don't forget to up vote the answer if you find it helpful.
thanks for the quick reply, the error is fixed, but still not all the series are processed by the if clauses in the for cycle, for example this statement:
Else
ActiveChart.SeriesCollection(i).IsFiltered = True
End If
Isn't executed and I don't understand why.
I'm having a small issue manipulating data.
I have a few check-boxes to select various items on the screen, which in turn inputs relevant data such as item name, price, etc. The issue is that these names have to go onto a invoice, and I cannot get the names to transfer onto the invoice nicely.
The invoice has to record the items, but it needs to check to see if a item has been already applied to the invoice and this is what I'm having problems with.
How can I get items to collectively display on a sheet without any additional interactions (I just click the relevant checkbox instead of manually typing it in), and display them nicely.
The items 'Underlay and Extended Warranty' need to be displayed one after another, and not 2-3 boxes away.
Example:
Underlay Extended Warranty
I don't want this:
Underlay
Extended Warranty
Is there a solution to this?
Update:
This happens if I do it the way I know:
I solved this by making a custom Excel VBA Macro that basically tells us the cell that is free which is closest to the top of the invoice:
Public Function GetApplicableCell() As String
Range("C20").Select
If (IsEmpty(Range("'Invoice Sheet'!C20").Value)) Then
GetApplicableCell = "C20"
End If
If (IsEmpty(Range("'Invoice Sheet'!C21").Value)) Then
GetApplicableCell = "C21"
End If
If (IsEmpty(Range("'Invoice Sheet'!C22").Value)) Then
GetApplicableCell = "C22"
End If
If (IsEmpty(Range("'Invoice Sheet'!C23").Value)) Then
GetApplicableCell = "C23"
End If
If (IsEmpty(Range("'Invoice Sheet'!C24").Value)) Then
GetApplicableCell = "C24"
End If
End Function
It can be called by a =GetApplicableCell() from within the worksheet, and we can work with this to produce a workable solution.