I need a help and your wide experiences please.
Lets imagine a case:
Three Workbooks exists: Workbook1 & Workbook2 & Workbook3
The Workbook1 & Workbook 2 has two same columns: ColumnA & ColumnB (for Workbook1) & ColumnAA & ColumnBB (for Workbook2)
All data are unsorded.
All columns has a different number of rows.
Macro in Workbook3 will be run and assign data from Workbook1 according of ColumnA & ColumnB to Workbook2 to ColumnCC & ColumnDD.
No auxiliary columns are allowed.
I am solivng it now by the simple VLOOKUP macro column by column. But I am still geting same values in ColumnCC & ColumnDD. It means that a all found values are same according of first found value in ColumnC & ColumnD but there are different values in that columns after all. And I stucked just here because I do not know how to solve it by macro.
The result what I need to get on is shown on attached picture below.
Curently I am try to solve it using a combination of the functions IF & VLOOKUP but i do not know how to build the macro fot this case of two functions and I did not find a relevant example to rewrite it by analogous.
=IF(B:B="ano";VLOOKUP(A:A;[Workbook1.xlsx]Sheet1!$A:$D; 3; 0); "")
Result example & combined formula IF+VLOOKUP
I would be grateful for your help or find another simple way using a macro.
Thank you so much.
Example which hopefully can get you start.
Book1:2 is your Workbook2.xlsx - Book1:1 is your Workbook1.xlsx
On both workbooks, the rows value under HDR2 (column B) is either blank or "ano". Nothing else, no rows with value other than "ano" under HDR2 in both workbooks.
The expected result in Workbook2.xlsx :
Regarding the blue and yellow color as seen from the image above,
there is no result in HDR3 and HDR4 in book2 - because
Blue : fff has no ano in book2 although fff has ano in book1.
Yellow : although ggg has ano in book2, but ggg in book1 has no ano.
If that's the kind of result you expect, the code is something like this :
Sub test()
Dim wb1 As Workbook: Dim wb2 As Workbook
Dim rgWb1 As Range: Dim rgWb2 As Range
Dim cWb1 As Range: Dim cWb2 As Range
Dim concWb1 As String: Dim concWb2 As String
Set wb1 = Workbooks("Book1.xslx") 'change as needed
Set wb2 = Workbooks("Book2.xslx") 'change as needed
With wb1.Sheets("Sheet1") 'change as needed
Set rgWb1 = .Range("A2", .Range("A" & Rows.Count).End(xlUp)).Offset(0, 1)
End With
With wb2.Sheets("Sheet2") 'change as needed
Set rgWb2 = .Range("A2", .Range("A" & Rows.Count).End(xlUp)).Offset(0, 1)
End With
For Each cWb2 In rgWb2.SpecialCells(xlCellTypeConstants)
concWb2 = cWb2.Offset(0, -1).Value & cWb2.Value
For Each cWb1 In rgWb1.SpecialCells(xlCellTypeConstants)
concWb1 = cWb1.Offset(0, -1).Value & cWb1.Value
If concWb2 = concWb1 Then
cWb2.Offset(0, 1).Value = cWb1.Offset(0, 1).Value
cWb2.Offset(0, 2).Value = cWb1.Offset(0, 2).Value
Exit For
End If
Next
Next
End Sub
The process:
It set the data range under HDR2 for both workbooks, as rgWb1 and rgWb2 variable. As the "rule" I've said before, since the rows under HDR2 will be only either blank or "ano" in both workbooks, so the code loop only to each cell (as cWb2 variable) which has value in rgWb2, concat the cWb2 value with the cell to the left value as concWb2.
Then it loop to each cell (as cWb1 variable) which has value in rgWb1 and also do the concat the cWb1 value with the cell to the left value as concWb1.
It check if concWb2 value = concWb1 value, then it put the value of cWb1.Offset(0, 1) to cWb2.Offset(0, 1) and put the value of cWb1.Offset(0, 2) to cWb2.Offset(0, 2).
FYI, with the "rule" for the rows under HDR2 in both workbooks like that, actually the code doesn't need to do the concatenate (concWb1 and concWb2). Anyway, I just have it to do the concatenate.
Please note, the code assumed that the data under HDR1 in both workbooks are all unique.
I'm writing an Excel workbook to take data for a research study, analyze each day's worth, then send the entered data and its 7 summary computations into a workbook (named test subject 1, and worksheet test med 1) for archive and analysis.
The range.copy command correctly copies the range of the data entered directly (or by a Userform) and the cells with the descriptive titles.
The column P, which contains data referenced from another sheet in the Workbook, is copied with the wrong cell reference. Cell AB16 is copied with the data from ='[FAVor Study Medication Daily Calculator8.xlsm]Calculations'!AB7, (not ...AB16). This is true for all the 7 summary cells in that column (AB16 - AB22), but cells ab15 and ab23, simple references to other cells on the same worksheet, are correctly copied.
I tried using the PasteSpecial command but got another set of problems that I'll try to solve next!
I've labelled the problem line of code as ProblemLine:
Dim wsCopyfrom As Worksheet
Dim wsCopyto As Worksheet
'Dim CopyfromLastRow As Long
'Dim CopytoLastRow As Long
'set variables for copy and dest sheets
Set wsCopyfrom = ThisWorkbook.Sheets("EnterData")
Set wsCopyto = ActiveWorkbook.Sheets(medname)
'Find last used row in the copyfrom based on data in column E and the copyto Col A
CopyfromLastRow = wsCopyfrom.Range("E200").End(xlUp).Row
CopytoLastRow = wsCopyto.Range("A200").End(xlUp).Row
'make copy of range, but ensure that all of the block rows are included, to row 10
If CopyfromLastRow > 19 Then
wsCopyfrom.Range("A7:P" & CopyfromLastRow).Copy wsCopyto.Range("A" & CopytoLastRow + 1)
Else
'ProblemLine
wsCopyfrom.Range("A7:q20").Copy wsCopyto.Range("A" & CopytoLastRow + 1)
End If 'if to copy at least to row 19
This is expected "Relative Reference" behviour. Same thing would happen if you manually copied those ranges in Excel yourself.
Two option to solve this:
Change your formula on the sheet to "Absolute References" eg ='[FAVor Study Medication Daily Calculator8.xlsm]Calculations'!$AB$16
Change your code to not use Copy, eg
wsCopyto.Range("A" & CopytoLastRow + 1).Formula = wsCopyfrom.Range("A7:Q20").Formula
Let me try to be more clear:
Here's an image that illustrates what I'm trying to do.
Essentially, my goal would be to have a formula that I could put into cell A2 (or a macro, if necessary) that would insert the name of the sheet that cell B2 comes from. In this case, that would be Sheet2. I've tried a bit through the macro recorder, but I haven't been able to get anything to work the way I want it to.
Ideally, I'd be able to select a cell (in this case, cell A2) and activate a macro or put in a formula that would populate that cell (A2) with the Sheet that the cell to the right of it (B2) comes from.
Thanks a ton for your help, any guidance as to what I should use for this or how I could do this would be hugely appreciated.
Here's a UDF that will pull the sheet name for a simple =SheetX!RANGE formula. It will also alert if there are multiple sheet references or none at all.
Place this in a standard module and in a cell type =ReturnSheet(B2)
Function ReturnSheet(rng As Range) As String
Dim sFormula As String
sFormula = rng.Formula
If InStr(1, sFormula, "!") = 0 Then
Dim sSheet As String
sSheet = "No sheet precedents found!"
Else
If UBound(Split(sFormula, "!")) = 1 Then
sSheet = Mid(sFormula, 2, InStr(1, sFormula, "!") - 2)
Else
sSheet = "Multiple Sheet precendents!"
End If
End If
ReturnSheet = Replace(sSheet,"'","") 'replace single quote in sheet names that has spaces
End Function
I know VBA is probably the way to go but I believe this can be done using a few basic formulas.
I need "E2" to be replaced (cut/copy) with the contents from "A3" but only if "D2" = "Status:Active"...and so on down the sheet
the yellow and blue color-coding are only for this example and do not represent the whole sheet
this is a 7,000 line spreadsheet that was a report generated off some old system and I'm trying by best to collate and format.
Try in Column F starting with cell F2
=if(AND(E2="",D2="Status: Active"), A2, E2)
This will test to see if D2 has "Status: Active" and if it does, it will pull the value form A2. If it isn't then it will use the address already in E2
As explained in your comments that you are looking for A to be blank when F accepts a value from it (Cut/Paste)... there is no way for a formula to affect another cell, but... You could add a new Column B inserted after A and put the following formula in there: =if(A2<>G2, "", A2). Then hide Column A. The new B column will then only show values of Column A when it's not already in Column G (formerly column F before the insertion of the new column).
You could also do all of this through VBA, but that seems like more effort than it's worth when some simple formulas will get you there.
Seeing as you want the column A to be blank you can try this macro out:
Option Explicit
Sub SwapCols()
Dim oWs As Worksheet
Dim lRowNum As Long
Dim i As Long
Set oWs = ActiveWorkbook.Worksheets("Sheet1")
lRowNum = oWs.Range("A2").End(xlDown).Row
For i = 2 To lRowNum
If oWs.Range("D" & CStr(i)).Value = "Status:ACTIVE" Then
oWs.Range("E" & CStr(i)).Value = oWs.Range("A" & CStr(i)).Value
oWs.Range("A" & CStr(i)).Value = Null
End If
Next i
End Sub
Make sure you replace "Sheet1" with the name of your sheet. the macro basically checks if a cell in column D has the value "Status:ACTIVE" and if it does it copies the corresponding cell in column A to column E.
Just make sure if you do run this and you do not like the results do not save.
I want to check Column A (A1:A365) in Sheet2, Sheet3, Sheet4 and Sheet5 and find Maximum value for each cell. Compare A1 in Sheet2, Sheet3, Sheet4 and Sheet5, find maximum of it and report it in A1 in result page. Also in cell B1 report corresponding sheet for this maximum. This goes on to Column A (A1:A365)
the following code i used:
Worksheets("sheet2").Range("A1").Value = a
Worksheets("sheet3").Range("A1").Value = b
Worksheets("sheet4").Range("A1").Value = c
Worksheets("sheet5").Range("A1").Value = d
MaxValue = Application.Max(a, b, c, d)
Range("A1").Value = MaxValue
yes i have just 4 sheets – Mohsen 11 mins ago
Non VBA Solution
In Sheet1, Cell A1, put this formula
=MAX(Sheet2!A1,Sheet3!A1,Sheet4!A1,Sheet5!A1)
In Sheet1, Cell B1, put this horrifying formula. I am sure there is a better way to find the sheet name though.
=IF(Sheet1!A1=Sheet2!A1,RIGHT(CELL("filename",Sheet2!A1),LEN(CELL("filename",Sheet2!A1))- FIND("]",CELL("filename",Sheet2!A1),1)),IF(Sheet1!A1=Sheet3!A1,RIGHT(CELL("filename",Sheet3!A1),LEN(CELL("filename",Sheet3!A1))- FIND("]",CELL("filename",Sheet3!A1),1)),IF(Sheet1!A1=Sheet4!A1,RIGHT(CELL("filename",Sheet4!A1),LEN(CELL("filename",Sheet4!A1))- FIND("]",CELL("filename",Sheet4!A1),1)),IF(Sheet1!A1=Sheet5!A1,RIGHT(CELL("filename",Sheet5!A1),LEN(CELL("filename",Sheet5!A1))- FIND("]",CELL("filename",Sheet5!A1),1)),""))))
A word of caution though. To use the RIGHT(CELL("filename",Sheet2!A1),LEN(CELL("filename",Sheet2!A1))- FIND("]",CELL("filename",Sheet2!A1),1)), you need to have the workbook saved.
My Sheet2, A1 has 1, Sheet3, A1 has 2, Sheet4, A1 has 2.5,Sheet5, A1 has 3
VBA Solution
Sub Sample()
Dim ws As Worksheet
Dim i As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
.Range("A1:A365").Formula = "=MAX(Sheet2!A1,Sheet3!A1,Sheet4!A1,Sheet5!A1)"
.Range("A1:A365").Value = .Range("A1:A365").Value
For i = 1 To 365
Select Case .Range("A" & i)
Case ThisWorkbook.Sheets("Sheet2").Range("A" & i).Value: .Range("B" & i).Value = "Sheet2"
Case ThisWorkbook.Sheets("Sheet3").Range("A" & i).Value: .Range("B" & i).Value = "Sheet3"
Case ThisWorkbook.Sheets("Sheet4").Range("A" & i).Value: .Range("B" & i).Value = "Sheet4"
Case ThisWorkbook.Sheets("Sheet5").Range("A" & i).Value: .Range("B" & i).Value = "Sheet5"
End Select
Next i
End With
End Sub
Quick solution
Based on Sidd's answer, here's my non-VBA solution without the horrifying formula:
Place this formula in Sheet1!A1: =MAX(Sheet2:Sheet5!A1)
As the sheet name does not have to be flexible (I'd assume you don't change it that often), you can use this formula in B1:
=IF(Sheet2!A1=A1,"Sheet2",
IF(Sheet3!A1=A1,"Sheet3",
IF(Sheet4!A1=A1,"Sheet5",
"Sheet5")))
More structural solution (better suited for many worksheets):
If you have many worksheets, you could consider this alternative.
Have a list of the relevant worksheets stored somewhere in your worksheet. (in the example, I place the list in E3:E7). Name this range Sheets. (Similar to Sidd's horrifying formula, I used the CELL formula to dynamically get each sheet name. However, this is not necessary in a static model)
(same as step 1 above): Place this formula in Sheet1!A1: =MAX(Sheet2:Sheet5!A1)
Place this formula in A2:
=INDEX(Sheets,MATCH(1,COUNTIF(INDIRECT("'"&Sheets&"'!A1"),A1),0))
Enter it as an array formula, i.e. press Ctrl-Shift-Enter instead of Enter.
I uploaded the second solution here.
Kudos to this instruction!
Since the formula is intended to be copied down, you don't want to hard-code a reference to cell A1 in the INDIRECT in Peter Albert's formula. You can use CELL("address",A1) to get a reference to A1 that can be copied down instead.
You can also avoid the need to array-enter the formula by using LOOKUP to return the result instead of INDEX & MATCH.
Note that LOOKUP will return the name of the last worksheet with the max value in case of a tie.
The following formulas use a named range Sheets with the names of each worksheet
=MAX(Sheet2:Sheet5!A1) returns max value (identical to Peter Albert's formula)
=LOOKUP(2,1/COUNTIF(INDIRECT("'" & Sheets & "'!" & CELL("address",A1)),A1),Sheets) returns name of sheet with max value
Make two new sheets with one titled "First" and the other "Last". Make new sheets for your project originate through a button that contains a macro to add duplicate sheets between "First and Last". Then just put one of these simple formulas for example in your reporting cell: =SUM(First:Last!K28) or =MAX(First:Last!K28)