Using Indirect within Advanced Filter - vba

Hello Stack Overflow Community,
I am currently creating an automated report that imports two or more CSV files from a given folder. The unique identifier that I need to use for a VLOOKUP is in an obscure column, so what I needed to do was Cut and Insert the found column onto Column 'A'. Example Below.
With wksRawData
'~~> Move Process ID Column to Column 'A' for VLOOKUP
.Columns(WorksheetFunction.Match("pid", .Range("1:1"), 0)).Cut
.Columns(1).Insert Shift:=xlToLeft
'~~> Remove Additional Headers
.Cells.RemoveDuplicates Columns:=Array(1)
End With
This part works great, but I have a formula in another worksheet that is supposed to reference $A2 and it gets changed to $B2. The reason why it should reference $A2 is because it is being used in an Advanced Filter Formula, and is the very first data point. Formula Below.
=IF(COUNTIF($C:$C, 'Raw Data'!$A2)=0, TRUE, FALSE)
When used in tandem with the other Advanced Filter columns this formula will whitelist any manually added unique identifiers. Example Below.
PID Whitelist | | user | proc | PID Whitelisted?
---------------+------+--------+----------------+------------------
182 | | root | | < FORMULA_ABOVE >
11 | | test | | < FORMULA_ABOVE >
1776 | | | Jazzy Rabbit | < FORMULA_ABOVE >
I've attempted to use INDIRECT, ADDRESS, and INDEX in the place of 'Raw Data'!$A2, but since they reference an absolute destination the Advanced Filter always uses the very first unique identifier value; instead of the current row's value.
Thank you in advance for your time, and I really appreciate any assistance provided!
NOX

I would suggest simply rewriting the formula immediately after the VBA column insert. Example (with improved (?) formula:
With wksRawData
'~~> Move Process ID Column to Column 'A' for VLOOKUP
.Columns(WorksheetFunction.Match("pid", .Range("1:1"), 0)).Cut
.Columns(1).Insert Shift:=xlToLeft
'~~> Remove Additional Headers
.Cells.RemoveDuplicates Columns:=Array(1)
End With
sheets("Some_Sheet").cells(x, y).formula = "=NOT(COUNTIF($C:$C, 'raw data'!$A2))"

'aslo one additional variant of the #Jeeped idea, without formulas
With wksRawData
.Columns(Range("1:1").Find("pid").Column).Cut
.Columns(1).Insert
.Cells.RemoveDuplicates Columns:=Array(1)
End With
Sheets("Some_Sheet").Cells(x, y).Value = _
WorksheetFunction.CountIf(Columns(3), Sheets("raw data").Cells(2, 1).Value)

Related

Combining Text and Hyperlink Into Text that is Hyperlinked

I have text in column A and URLs in column B.
I want the merged A&B shown in column C.
Example:
Column A | Column B | Column C
Product 1 | google_dot_com | Product 1 (with hyperlink to url)
Product 2 | yahoo_dot_com | Product 2 (with hyperlink to url)
Product 3 | stackoverflow_dot_com | Product 3 (with hyperlink to url)
Here is an image.
This is different from just referencing the cells and using the HYPERLINK(A1,B1) and then copying it down column C.
Here is a small test file I created that you can download if my above example wasn't clear enough. http://www.filedropper.com/stacker-help
Using Microsoft Office Professional Plus 2013, Windows 7
=HYPERLINK(B2,A2) should work as per your image requirement. Please check
store the link(column B) in text format
Use the CONCATENATE-Funktion in Excel, e.g.=CONCATENATE(A1;B1).
If you need the square bracets just add them in eg.g =CONCATENATE(A1;"[";B1;"]").
The function-names in Excel depend on your language, you might have to use a translated version (in Germany 'VERKETTEN', other languages see http://en.excel-translator.de/CONCATENATE/).
And it gets better: in german you need ";" to seperate the parameters, in english it's a ",".
Translating funktion-names like in Excel should be considered a crime.
I have found the answer I was looking for, here is the VBA code I used.
Sub MergingCells()
For i = 2 To Range("a1").End(xlDown).Row
Sheets("sheet1").Hyperlinks.Add anchor:=Cells(i, 3), Address:="http://" & Cells(i, 2).Value, TextToDisplay:=Cells(i, 1).Value
Next i
End Sub

Excel 2007 VBA - Using Sheets.Add to create a chart at the end of a workbook

I'm trying to implement a private subroutine to add a Sheet to the active workbook (Sheet being used so that one can choose to add xlForms, xlWorksheet, etc).
But I'm having a bizarre problem with where new charts get created relative to the other sheets in the workbook.
I start off by deleting the sheet of the same name (if it exists) and then use the following code:
ActiveWorkbook.Sheets.Add(After:=Sheets(Sheets.count()), _
Type:=sheet_type).Name = sheet_name
Where sheet_type is an optional parameter of the enum XlSheetType, and sheet_name is a string.
It works completely fine for every available argument such as xlWorksheet, xlDialogSheet, and even the xl4MacroSheet -- but for some reason will create the xlChart 1 position before the end, as opposed to the making it the last sheet in the workbook.
So sample I/O (starting off with only 3 sheets):
> Create_Sheet "Test", sheet_type:=xlWorksheet
Sheet 1 | Sheet 2 | Sheet 3 | Test
> Create_Sheet "Test", sheet_type:=xlDialogSheet
Sheet 1 | Sheet 2 | Sheet 3 | Test
> Create_Sheet "Test", sheet_type:=xlChart
Sheet 1 | Sheet 2 | Test | Sheet 3
Sheets.count() properly returns 3 in the previous examples (because I start with only Sheets 1, 2, and 3), and so it should hypothetically position it after the 3rd sheet, but it doesn't.
Attempting to do Sheets.count() + 1 for testing only gives me an array subscript out of range runtime exception (which is to be expected).
I've even tested just the base code of:
ActiveWorkbook.Sheets.Add(After:=Sheets(Sheets.count()), _
Type:=xlChart).Name = "Test"
and I still wind up getting the same result.
So basically my question is this: am I doing something wrong here? Is there any specific reason as to why a chart can't be added to the end of the Workbook? Or is this perhaps a problem/bug in VB that needs to be fixed?
I'm using Office 2007, so alternatively is it an error that has been fixed in newer versions?
Any input would help.
EDIT:
It's worth noting that After:=Sheets(Sheets.count()) produces the same location as After:=Sheets(Sheets.count() - 1), but only in the case that Type:=xlChart
EDIT 2
This is even more interesting. If you create one Chart, place it as the last sheet in the workbook, and use the following code:
ActiveWorkbook.Charts.Add After:=Charts(1)
Excel will automatically re-orient the charts so that a Worksheet is last.
For example, if you have:
Sheet 1 | Sheet 2 | Sheet 3 | Chart 1
and use the code, you will get
Sheet 1 | Sheet 2 | Chart 1 | Chart 2 | Sheet 3
Ok, I am not sure if this will help you, but yes, it has the same odd behavior here, and could not find any "clean" way to make the sheet last, so my solution was that:
ActiveWorkbook.Sheets.Add(After:=Sheets(Sheets.Count()), _
Type:=xlChart).Name = sheet_name
Sheets(sheet_name).Move After:=Sheets(Sheets.Count())

VBA - Index / Match function with multiple criteria

I am facing an issue when trying to compile a multiple criteria Index/Match code in VBA. This might be simple - but i am fairly new to VBA and nothing i have found around here worked.
Example:
I have a large amount of data in a specified range: Sheets("CustomerAccounts").Range(CustomerSheetRange)) - I need VBA to return data from column titled "Values" by checking three criteria: Customer = X, Type = External, OriginCountry = UAE (columns are not adjacent in the original spreadsheet)
The criteria are stored in separate variables set by user of the macro beforehand.
Customer | Type | Origin | Destination | Values
X | Internal | UAE | SA | Value 1
Y | Internal | UAE | SA | Value 2
X | External | UAE | SA | Value 3
X | External | ZA | UAE | Value 4
At the moment i have the following (quite bulky) code which finds the value using one criteria - OriginCountry variable.
The code searches for it in a pre-specified column - OriginCountryColumn.
ResultString = Application.Index(Sheets("CustomerAccounts").Range(CustomerSheetRange), Application.Match(OriginCountry, Sheets("CustomerAccounts").Range(OriginCountryColumn), 0), Application.Match("Values", Sheets("CustomerAccounts").Range(TitleRowCust), 0))
I would like to modify the code to also match the Type and The customer.
Is it possible to expand the above Index/Matxh function - or should i use a different approach?
Any advice is appreciated.
You may walk through rows checking matches:
Dim row as Long
With Sheets("CustomerAccounts").Range(CustomerSheetRange))
For row = 2 To .Rows.Count 'Starts in 2 to ignore header!
If .Cells(row, costumerCol).Value Like costumerCriteria And .Cells(row, typeCol).Value Like typeCriteria And .Cells(row, originCol).Value Like originCriteria Then
'This is a match!
Debug.Print .Cells(row, valueCol)
End if
Next
End With
You must replace costumerCol, typeCol, originCol and valueCol with corresponding column number and costumerCriteria, typeCriteria and originCriteria with criteria specified.
If column indexes are also variable, make a search for them in first row before walking through rows.
First, format the range containing your data to a Table (See http://office.microsoft.com/en-001/excel-help/quick-start-create-an-excel-table-HA010359200.aspx on how to do that). Once done, use the following VBA code:
SomeCustomer = Range("...").Value
SomeType = Range("...").Value
SomeOrigin = Range("...").Value
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria=SomeCustomer
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=2, Criteria=SomeType
ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=3, Criteria=SomeOrigin
Notes:
You might have to customize this macro for your specific needs
Name of table can be found/modified through Formulas>Name Manager
ActiveSheet might be modified to the actual sheet you are using

VBA for checking rows and returning cells that match criteria to another sheet

I’m struggling trying to develop an automated solution for the following challenge (ie apart from a button press, no user intervention):
I have a master ‘sheet that contains Accrual figures in monthly columns and an associated Receipt Number for this in a column immediately to the right. The Receipt columns have the month in the form: ‘Feb’, ‘Jun’, ‘Dec’ at the top.
I need to return a variety of cell data to another summary ‘sheet in the workbook from each row that matches the following criteria:
Identify the Receipt column based on a match of the month with an entered month in cell ‘x’ in the summary ‘sheet, eg if I type ‘Mar’, find the column headed ‘Mar’ in the master ’sheet.
Ignoring blank rows (ie there are data in Column A), if the cell in the first row of the Receipt column is blank, identify the row, select 6 different cells and return the contents to 6 specific cells in the first blank row (from a given row number) in the summary ‘sheet – then move onto the next row in the column and continue this process until the end (or a row limit). NB: the 'blank' cell will have a fill colour (conditionally formatted).
If the cell contains data, move to the next row down and continue the process.
A VBA routine I can attach to an onscreen button to update the results each time would do the job nicely. Although I've picked up bits of really useful code here, eg for checking each row for given conditions, I can’t get my head around a working solution to include returning the relevant cells to the summary 'sheet...
Any and all feedback greatly appreciated.
(Sorry - can't post images / screenshots yet...)
Update
Thanks for the quick response, and apols I couldn't append/paste-in a sample of the spreadsheet - apparently I need 10 points... :)
Slightly Different summary sheet (Sheet1). The columns are: Month (Col A), then 4 cells (TBD) to be returned to cols B-E, then Receipt No (Col F). The data come from each identified row in the master sheet (Sheet4) and are placed in the next available blank row in Sheet1. I can mod any examples given to match the actual positions.
I have the criteria for selecting the row (this is from a loop I've got working to identify the row, but using a fixed column reference [26 - Col Z] for a specific month):
If Not Cells(TheRow, 3).Value = "" And Cells(TheRow, 26).Value = "" And Cells(TheRow, 6).Value < Cells(TheRow, 25).Value Then... (do the other bit I'm stuck on)
Hope this is a bit clearer. Appreciate your help.
Can't add a comment, or chat (!) so further update:
Thanks Tony
The month column in the summary is to confirm the month reported on, as this will change when the user overwrites the source cell for the month they wish to parse the master sheet with. The person this data goes to will get these 7 columns and nothing else.
The mechanism has to find the Receipt col (month), then identify that row entry is blank AND col 3 on that row is not blank AND that the Accrual value [Rng.Column - 1] is greater than the PO value (Col 4) on that row. Once these criteria are established, the Receipt, Accrual, PO and 3 other data are selected, copied and pasted into the summary sheet on the next available blank row.
The master sheet has Accrual and Receipt for each month, so there is only one column to identify.
Hope this helps...
I am struggling to visualise you worksheets. I see the master sheet as something like:
... |Accrual| Jan|Accrual| Feb|Accrual| Mar|Accrual| Apr| ...
... | 1.23|A12 | | | 23.67|A14 | | |
... | | | 56.78|C34 | 178.12|C56 | | |
... | 2.34|B678 | | | | | 123.82|B821 |
... | | | | | 96.52|D56 | | |
Somewhere within the Summary sheet there is a list of months of interest.
I need a variable:
Dim MonOfInt As String
and a loop within which a month of interest will be loaded from the worksheet into this variable:
With Sheets("Summary")
MonOfInt = .Cells(R, C).Value
End With
The following is a possible skeleton for the code to move values for the month of interest:
Dim ColCrnt As Long
Dim Rng As Range
Dim RowCrnt As Long
Dim RowLast As Long
:
With Sheets("Master")
' Look for month of interest in row 1
Set Rng = .Rows(1).Find(MonOfInt)
End With
If Rng Is Nothing Then
' No columns for this month in Master
Else
' Accrual and Receipt columns for this month found
ColCrnt = Rng.Column - 1 ' Accrual column for month
' Find last used row in Accrual column
RowLast = .Cells(Rows.Count, ColCrnt).End(xlUp).Row
For RowCrnt = 2 To RowLast
' Code to extract values from Master and move to Summary here
Next
End If
End With
If you can add information to your question to confirm my visualisation and to give more information about (1) how to detect is a row is blank (other than testing the whole row which is an option) and (2) the source and destination of the six cells then I will try to pad out this answer.

Excel formula to calculate diff b/w 1st value and last value in a column (Excel)?

I have the following columns : (Using Excel Formula)
A B
------------------------
1 | Date | Value |
------------------------
2 | 8/20/2011 | 92.8 |
3 | 8/21/2011 | 92.4 |
4 | 8/22/2011 | 91.8 |
5 | 8/23/2011 | 90.7 |
6 | 8/24/2011 | 91.1 |
7 | 8/25/2011 | |
8 | 8/26/2011 | |
9 | 8/27/2011 | |
------------------------
I want to calculate the difference between 1st Value (B2) and last Value (last populated row in column B)
Edited :
Using formula : =B2-B6 is not what's required. (I want diff in Cell C2)
I want when the user enters the value in B7 it automatically shows the difference between B2 and B7, when he populates B8 then it shows the diff between B2 and B8 and so on..
I don't want some direct method to do this in Excel and not by iterating all values to check the last value. Please suggest the best method to this in Excel.
This is more of a logic problem !
A Pure Excel solution is welcome, I can do that manually.
Edited:
Using Excel formula !
I hope I explained my problem properly..
If the headers are in A1 and B1, and your table is A2:B9 for instance, use the formula:
=$B$2-OFFSET($B$2,COUNTA($B$2:$B$9)-1,0,1,1)
To find the last number in a column you can use VLOOKUP on a single column where 1E+99 is the lookup_value and the optional range_lookup is left to the default. The data does not have to be sorted.
     
The formula in C2 is =VLOOKUP(1E+99,$B$2:$B$99,1)-B2. Similarly, you can locate the last non-blank alphabetic value with =VLOOKUP("zzzzz",$E$2:$E$99,1) (example in F2).
To find the last non-blank value where there are mixed alphabetic and numeric values, use INDEX and apply MAX to MATCH, e.g. =INDEX(E2:E99,MAX(IFERROR(MATCH(1E+99,E2:E99),0),IFERROR(MATCH("zzzz",E2:E99),0))). Any of these formulas could easily be adjusted to return a value from another column corresponding to the last value in the lookup column.
I understand you are not looking for a pure Excel solution but you can use it a different way >> you can add an Excel formula with vb/vba.
Something like =B7-$B$2 is the formula needed.
Thus, you can do something like:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B:B")) Is Nothing Then
Target.Offset(0, 1).Formula = "=" & Target.Address & "-$B$2"
End If
End Sub
Another less elegant way to do this with Excel formulas alone, would be to use a helper column, which is a telescoping series.
In column C2, enter 0.
In columns C3, use the formula
=IF(B3="",0,B2-B3)
Copy down the length of the table.
At the bottom, sum everything in the helper column.