sorry for being a total noob in excel!
I have two sheets, sheet 1 named "Stocks" and sheet 2 named "Stocks search".
In "Stocks" I have from A1 to B700 values. In A column I have the stocks symbols and in B column I have the stocks' issuers symbols, so every entry in A column is unique, yet there can be repeating entries in column B.
So in sheet "Stocks search", if I enter in A1 an issuer's symbol, I want for the formula to go search in sheet "Stocks" and fetch all stocks that this issuer has in new rows.
How can this be done in a formula? Thanks in advance!
This is a VBA solution to the question. IMHO, this is more appropriate than a formula (in this case). The formula approach is OK, but there are drawbacks - you have to remember the CSE rule, and then copy the formulas down the right number of rows (which you don't know in advance), etc, etc.
This code uses the same assumptions as the formula approach.
1 - sheets = Stocks and Stock report
2 - Data in Sheets, columns A and B (header in row 1)
3 - lookup code is on Stock report
4 - Output is on Stock report
One of the advantages is that if new data is added to the Stocks sheet (i.e. the bottom row > 700), the vba automatically adjusts.
The code is self-documented. But the essence is that it creates an autofilter on "Stocks" using the lookup value as the criterion; copies the rows that meet the criteria; and pastes the result to an output range on "Stock reports". The output range is cleared before the copy/paste takes place so that there are no left-overs from any previous lookup.
I think there's something to be said for creating a dropdown list for the lookup cell. No doubt that could be automated too by getting the codes from Column A, getting the unique values, and then apply them to the lookup cell. Just a thought;)
Sub so_52537740()
' CREDITS
'
' Refer: https://stackoverflow.com/questions/17531128/copy-paste-calculate-visible-cells-from-one-column-of-a-filtered-table
' Date: 8 July 2013
' Submitted by: Jon Crowell (https://stackoverflow.com/users/138938/jon-crowell)
Dim src As Worksheet, tgt As Worksheet
Dim filterRange As Range, copyRange As Range
Dim lastRow As Long
Dim stocks As String, stockreport As String
' set values for sheet names
stocks = "Stocks"
stockreport = "Stock report"
' set values for Sheet variables
Set src = ThisWorkbook.Sheets(stocks)
Set tgt = ThisWorkbook.Sheets(stockreport)
' clear the exist target data
tgt.Range("A4:B" & Rows.Count).ClearContents
' turn off any autofilters that are already set
If src.AutoFilterMode Then src.AutoFilter.ShowAllData
' find the last row in the Stocks sheet with data in column A
lastRow = src.Range("A" & src.Rows.Count).End(xlUp).Row
' the range that we are auto-filtering (all columns)
Set filterRange = src.Range("A1:B" & lastRow)
' the range we want to copy (only columns we want to copy)
' in this case we are copying both columns A and B
' we set the range to start in row 2 to prevent copying the header
Set copyRange = src.Range("A2:B" & lastRow)
' filter range based on column A being equal the the value in Cell A1 of the stockreport
' consider making this a dropdown list so that there are no errors
filterRange.AutoFilter field:=1, Criteria1:=Format(Sheets(stockreport).Range("a1").Value)
' copy the visible cells to our target range
' note that you can easily find the last populated row on this sheet
' if you don't want to over-write your previous results
copyRange.SpecialCells(xlCellTypeVisible).copy tgt.Range("A4")
' turn off any autofilters that are already set
If src.AutoFilterMode Then src.AutoFilter.ShowAllData
End Sub
Giving due credit: There is, as they say, nothing new under the sun. I have based this answer on an excellent piece of work by Jon Crowell on a question in StackOverflow "Copy/Paste/Calculate Visible Cells from One Column of a Filtered Table" in July 2013. Just goes to show what a bit of Googling and perseverance can achieve.
I believe I have an answer for you.
Try
=IFERROR(INDEX('Stocks Search'!$A$1:$A$700,SMALL(IF('Stocks Search'!$B$1:$B$700=$A$1,ROW('Stocks Search'!$A$1:$A$700)-MIN(ROW('Stocks Search'!$A$1:$A$700))+1),COLUMNS($A$1:A1))),"")
This is a CSE formula. What that means is once you enter it into cell B1, you will need to press Control+Shift+Enter. Once you do this, these brackets will appear around your formula {}
Click the fill button in the bottom right of the cell and drag the formula to the right (you will need to do this for as many cells as it is possible for answers). So if Company A has 40 possible answers, you will need to have this formula go at least 40 cells to the right.
The application of CSE formulas can be tricky. Essentially you need to go to the end of the formula in the formula bar, and then use Control+Shift+Enter.
I hope this helps.
Related
I am new to VBA Excel.
I wanna create a database for each month, with 1 'Main Sheet' for the list of names, and the list on 'Main Sheet' will sort automatically as a row when I entered data along with the update of the other sheet.
I found this code, and it's only updated/sorting in the sheet entered (let's say the 'Main Sheet'). Is that possible if the entered data and sorting updated automatically in all other sheets?
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.Column = 1 Then
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
Range("A2:BN2" & lastRow).Sort key1:=Range("A2:A" & lastRow), order1:=xlAscending, Header:=xlNo
End If
End Sub
I tried referencing/paste the link to the name for each month (start from A2), but I have no idea to keep the column beside A2 (B2, C2, etc) sticking with the A2 as a full row.
Thanks!
Look at this part of your code for ideas how to solve your problem.
Range("A2:BN2" & lastRow).Sort Key1:=Range("A2:A" & lastRow)
The instruction is to sort Range("A2:BN2" & lastRow) on Key1. The range to sort starts at A2 and ends with the last used row in column BN. All columns of all rows are included, as they should. But lastRow was determined in column 1, which is column A. We hope that all columns have the same length. Observe that we don't know on which tab the range is located. By default, if no sheet is specified, Excel will presume the ActiveSheet. This is borne out by the fact that the code is located in a worksheet event procedure. Of course, this code is linked to the sheet on whose code module it is placed. It won't run when another sheet is active.
However, the syntax for specifying a range for a particular sheet would look like this.
With Worksheets("MySheet")
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
Set MyRange = .Range("A2:BN2" & lastRow)
End With
Please observe all the leading periods, each of which links the statement it precedes to the worksheet specified in the With statement. Imagine a loop in which the sheet name is changed on each turn, thereby defining the same range on a different sheet on each instance.
The Key argument of the Sort method specified the column on which to sort. It's called "Key" instead of "Column" because there are sheet columns and range columns. In your case the sheet rows are different from your range rows because your range starts in row 2 but the range columns are identical with the sheet columns. Anyway, Key1:=Range("A2:A" & lastRow) isn't a very good pointer to the column you want to sort on. 1 single cell would suffice, like Key1:=Range("A2") - or Key1:=Cells(2, 1) as I would prefer.
As you see, this part is a lot simpler. The only important point to observe is that the cell specifying the Key must be within the range to be sorted. This also means that you can't specify a Key on the ActiveSheet for a sort range on another tab. When you construct your loop, therefore, you will need to take a cell from the properly defined sort range as Key.
I have two excel sheets both with matching product numbers. What I need to do is match the product numbers and then copy a column from the first sheet to the second.
My example:
Column C in the first sheet contains product numbers
Column A in the second sheet contains product numbers
I want to match C & A and then copy column B from the first to the second sheet.
Sorry if this has been answered before, my knowledge is basic but I am trying to learn
Thanks for any help.
CD
Assuming your numbers to match start in C2 (headers in row 1) and numbers to copy in AC2 on Sheet1, this should do what you want. Paste it into AC2 on Sheet2 and then drag copy to the length of column A on Sheet2.
=IF(IFNA(MATCH(A2,Sheet1!C:C,0), FALSE), INDIRECT("Sheet1!AC"&MATCH(A2, Sheet1!C:C, 0)), "Not Found")
Note this will give "Not Found" for a value on Sheet2 which is not found on Sheet1, you can change that by just replacing the string "Not Found" in the formula with whatever you want (e.g. 0).
Formula:
You can use OFFSET with IF. In B1 of sheet 2 for example you could put, drag down for as many rows as required,
=IF(A1=Sheet1!C1,OFFSET(Sheet1!A1,0,COLUMNS(Sheet1!A:AC)-1,1,1))
If you set your data up as a table in sheet 2 (Ctrl + T with an populated cell selected) then add this formula to the appropriate column it will autofilter down the formula.
Or:
With code in a standard module:
Public Sub AddFormula()
Dim rng As Range
With Worksheets("Sheet2")
If Application.WorksheetFunction.Subtotal(103, .Columns(1).Cells) > 0 Then
For Each rng In Intersect(.Columns(1), .UsedRange)
If Not IsEmpty(rng) And Not IsError(rng) Then 'assume ignore empty cells
If rng = Worksheets("Sheet1").Cells(rng.Row, "C") Then Worksheets("Sheet1").Cells(rng.Row, "AC").Copy rng.Offset(, 1) 'determine where you want value to go
End If
Next rng
End If
End With
End Sub
Note:
This is based on your comment that you are comparing sheet2 col A with sheet1 col C and copying sheet1 col AC if match.
I assume that the product numbers in both sheets are unique. If that, I suggest use the offset and match formulas to achieve what you want.
sorry for my half-baked answer due to i just typed them with phone and it is not convenient to input complicated style, here is the additional information:
the match formula is used to query the location of the target product number in the original sheet( sheet 1 in your case above);
after we located the position of the target product number, extract the information you wanted through the offset formula.
here are the specific process:
Sheet 1 represent the original information and sheet 2 represent the target one. What we required to do is copy the info in col D of sheet 1 to col D of sheet through the product:
OFFSET($D$5,MATCH(I6,$D$5:$D$16,0)-1,1,1,1)
OFFSET($D$5,MATCH(I7,$D$5:$D$16,0)-1,1,1,1)
OFFSET($D$5,MATCH(I8,$D$5:$D$16,0)-1,1,1,1)
OFFSET($D$5,MATCH(I9,$D$5:$D$16,0)-1,1,1,1)
OFFSET($D$5,MATCH(I10,$D$5:$D$16,0)-1,1,1,1)
or you can refer to the output directly:
enter image description here
for more information about these two formulas, you can refer to the help of excel of google.
I have the following data:
Example:
A B C
EmployeeID EmployeeName EmployeeSalary
-------------------------------------------
E101 JAK 20000
E102 SAM 25000
E103 John 20000
E104 Shawn 30000
I have the cell H1 in which i type salary of the employee, and in the below cell that is cell H2, I2, J2 should list the employee details according to the given salary in the cell H1.
I have used VLOOKUP function for this.
For cell H2:
=IFERROR(VLOOKUP(H1,C2:A5,1,FALSE),"EmployeeID not found")
For cell I2:
=IFERROR(VLOOKUP(H1,C2:B4,2,FALSE),"EmployeeName not found")
For cell J2:
=IFERROR(VLOOKUP(H1,C2:C4,3,FALSE),"EmployeeSalary not found")
Note: The above works fine for single result to display but when i enter 20000 it will only show single record NOT all which meet the given criteria.
There are three ways to deal with this:
First the Formula:
I set up the Field as such which will become apparent with another method:
So in J4 I put the following formula:
=IFERROR(AGGREGATE(14,6,$C$2:INDEX(C:C,MATCH(1E+99,C:C))/($C$2:INDEX(C:C,MATCH(1E+99,C:C))=$H$2),ROW(1:1)),"")
In H4 I put:
=IF($J4<>"",INDEX(A$2:INDEX(A:A,MATCH(1E+99,$C:$C)),AGGREGATE(15,6,(ROW($C$2:INDEX($C:$C,MATCH(1E+99,$C:$C)))-1)/($C$2:INDEX($C:$C,MATCH(1E+99,$C:$C))=$J4),COUNTIF($J$4:$J4,$J4))),"")
Which I then drag across to I4. Then drag all three formulas down till you are sure you have covered all the possible results.
This is a non CSE array formula. Array formulas calculations are exponential, so we need to limit the reference range to the minimum needed. All the INDEX($C:$C,MATCH(1E+99,$C:$C)) finds the last cell with data and sets this as the end reference.
The IFERROR() wrapper on the first allows the formula to be copied down further than the list will return and avoid the #N/A. In the picture the formulas occupy the first 8 rows.
Second we use the Advanced Filter:
First we set up the area around H1 like this:
Then we navigate to Advanced Filter which is on the Data tab. This window pops open:
Then we enter the Information:
Mark the Copy to another location.
List Range is $A$1:$C$5
Criteria Range is $A$1:$C$5
Copy to range is $H$3:$J$3
Then hit okay.
The third is vba which mimic the Advanced Filter:
Sub atfilt()
Dim ws As Worksheet
Dim rng As Range
Dim critrng As Range
Dim cpytorng As Range
Dim lstrow As Long
Set ws = Sheets("Sheet9")
lstrow = ws.Range("A" & ws.Rows.Count).End(xlUp).row
Set rng = ws.Range("A1:C" & lstrow)
Set critrng = ws.Range("H1:H2")
Set cpytorng = ws.Range("H3:J3")
rng.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=critrng, CopyToRange:=cpytorng, Unique:=False
End Sub
Each has their disadvantages:
Formula: If the data set is large then(1,000 rows or more) the calculations will be long.
Advanced Filter: Each step must be redone each time a new filter is wanted. It is not automatic.
VBA: It is VBA and requires a certain understanding on how to use it.
I agree with #Scott Craner's comment that autofilter would be great here to allow you to find multiple values based on a criteria. Unfortunately (maybe someone can fill this bit in :)) I don't know much about autofilter in vba for this purpose (only used it once or twice)
I can tell you about left lookups with INDEX(MATCH()) which should work in place of your VLOOKUPS.
Format:
INDEX("column of values to return",MATCH("lookup value","column to find lookup value", 0))
so in your example for cell H2 you could use:
=IFERROR(INDEX($A:$A,MATCH(H1,$C:$C,0)),"EmployeeID not found")
Note the "0" in the formula is to find an exact match!
I would like to populate columns in sheet2 from sheet1. If I have column A in Sheet1 I want A in Sheet2 to have the same information.
I tried using =sheet1!A1 but it only returns the value from A1 in sheet1. I tried using =sheet1!A but it only returns #NAME?.
If Column A from Sheet1 has a dynamic range (it can be empty or have 500 or 1000 rows (I'm populating sheet1 from my database)). How do I use some of those columns in another sheet showing all 500 or 1000 rows?
If I understood you right you want to have sheet1!A1 in sheet2!A1, sheet1!A2 in sheet2!A2,...right?
It might not be the best way but you may type the following
=IF(sheet1!A1<>"",sheet1!A1,"")
and drag it down to the maximum number of rows you expect.
I have used in Google Sheets
={sheetname!columnnamefrom:columnnameto}
Example:
={sheet1!A:A}
={sheet2!A4:A20}
Below code will look for last used row in sheet1 and copy the entire range from A1 upto last used row in column A to Sheet2 at exact same location.
Sub test()
Dim lastRow As Long
lastRow = Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
Sheets("Sheet2").Range("A1:A" & lastRow).Value = Sheets("Sheet1").Range("A1:A" & lastRow).Value
End Sub
In Google Sheets you can use =ArrayFormula(Sheet1!B2:B)on the first cell and it will populate all column contents not sure if that will work in excel
Use the 'EntireColumn' property, that's what it is there for. C# snippet, but should give you a good indication of how to do this:
string rangeQuery = "A1:A1";
Range range = workSheet.get_Range(rangeQuery, Type.Missing);
range = range.EntireColumn;
So I've got this Workbook which contains a lot of data. And I've got this one sheet which basically copies the data based on certain conditions.
Each cell in each row looks like this (the last specified cell is the one where the formula is in):
=IF(Numbers1!E2<>0;Numbers1!A2;"")
=IF(Numbers1!E3<>0;Numbers1!A3;"")
=IF(Numbers1!E4<>0;Numbers1!A4;"")
=IF(Numbers1!E2<>0;Numbers1!B2;"")
=IF(Numbers1!E3<>0;Numbers1!B3;"")
=IF(Numbers1!E4<>0;Numbers1!B4;"")
So the formula in cell A2 is the first one, formula in A3 is the second line etc.
I want to copy the value from the same column and row from the sheet Numbers1, IF the value in the same row of column E is not 0. This seems to be working just fine.
But, when I update the data in Numbers1 sheet, the formulas are all of a sudden invalid and the formula now looks like this:
=IF(Numbers1!#REF!<>0;Numbers1!#REF!;"")
Each formula in each cells look identical to the formula above. And I can't have that, why can't Excel just keep the formula as it is without "helping" me?
Since you may be better off using a macro to rewrite your formulas, here are the basics:
Sub RewriteFormulas()
Dim row, col As Integer
row = 1 'row you want your target formulas to be on
For row = 1 To 60
For col = 1 To 13
ActiveSheet.Cells(row, col).Formula = "=IF(Numbers1!" & Cells(row,col).Address & "<>0,Numbers1!" & Cells(row+2,col).Adddress & ","""")"
Next row
Next col
End Sub
You can play around with using different sheets (or different workbooks) instead of just ActiveSheet so you can have 1 workbook that stores the macro and alters data in whatever workbooks provide your updated datasets.
Hope that helps...