I have an excel file with lots of sheets named "xxA" and "xxB" with xx being consecutive numbers.
Each sheet has the following format:
header1 header2 header3 header 4 header5
ingredient1 description xx 20 g
ingredient2 description xx 34 ml
ingredient3 description xx 56 g
and some other rows at the end.
Basically I want to create a new sheet in which rows 2-27 from column D are copied to a column named "value" and create two new columns with the number in the sheet name and another one with the letter like so:
subject condition ingredient value
21 A ingredient1 20
21 A ingredient2 34
21 A ingredient3 56
21 B ingredient1 34
21 B ingredient2 23
21 B ingredient3 47
...
I tried messing with pivot tables but that doesn't really work. I don't know how to create a VBA, so any direction on that would be great if that is the only way to go.
I think this is what you are looking for. It copies data from worksheets and gets the sheet names split as asked. I have it hard coded to only work for double digit numbers and single letters. Do you have sheets that do not fit that form? If so, I can rework my code!
ORIGINAL:
Sub SheetSummary()
'Make new worksheet with required headers
ActiveWorkbook.Sheets.Add
ActiveSheet.name = "Summary"
range("A1").Value = "subject"
range("B1").Value = "condition"
range("C1").Value = "ingredient"
range("D1").Value = "value"
Dim ws As Worksheet
Dim wsNum As String
Dim wsLetter As String
Dim wsLastRow As Long
Dim sumLastRow As Long
Dim myCell As range
Dim nextOpenRow As Long
'If a worksheet is not the summary, then get the data
For Each ws In Worksheets
If ws.name <> "Summary" Then
wsNum = Left(ws.name, 2)
wsLetter = Right(ws.name, 1)
wsLastRow = ws.Cells(Rows.count, "A").End(xlUp).Row
nextOpenRow = Cells(Rows.count, "A").End(xlUp).Row + 1
ws.range("A2", ws.Cells(wsLastRow, "A")).Copy
range("C" & nextOpenRow).PasteSpecial xlPasteAll
lastRow = Cells(Rows.count, "C").End(xlUp).Row
ws.range("C2", ws.Cells(wsLastRow, "C")).Copy
range("D" & nextOpenRow).PasteSpecial xlPasteAll
Application.CutCopyMode = False
For Each myCell In range("A2", Cells(lastRow, "A"))
If myCell.Value = "" Then
myCell.Value = wsNum
End If
Next myCell
For Each myCell In range("B2", Cells(lastRow, "B"))
If myCell.Value = "" Then
myCell.Value = wsLetter
End If
Next myCell
End If
Next ws
End Sub
EDIT:
Sub SheetSummary()
'Make new worksheet with required headers
ActiveWorkbook.Sheets.Add
ActiveSheet.name = "Summary"
range("A1").Value = "subject"
range("B1").Value = "condition"
range("C1").Value = "ingredient"
range("D1").Value = "value"
Dim ws As Worksheet
Dim wsNum As String
Dim wsLetter As String
Dim wsLastRow As Long
Dim sumLastRow As Long
Dim myCell As range
Dim nextOpenRow As Long
'If a worksheet is not the summary, then get the data
For Each ws In Worksheets
If ws.name <> "Summary" Then
wsNum = Left(ws.name, 2)
wsLetter = Right(ws.name, 1)
wsLastRow = ws.Cells(Rows.count, "A").End(xlUp).Row
nextOpenRow = Cells(Rows.count, "A").End(xlUp).Row + 1
ws.range("A2:A27").Copy
range("C" & nextOpenRow).PasteSpecial xlPasteAll
lastRow = Cells(Rows.count, "C").End(xlUp).Row
ws.range("D2:D27").Copy
range("D" & nextOpenRow).PasteSpecial xlPasteAll
Application.CutCopyMode = False
For Each myCell In range("A2", Cells(lastRow, "A"))
If myCell.Value = "" Then
myCell.Value = wsNum
End If
Next myCell
For Each myCell In range("B2", Cells(lastRow, "B"))
If myCell.Value = "" Then
myCell.Value = wsLetter
End If
Next myCell
End If
Next ws
End Sub
Since you don't know VBA I wouldn't recommend taking that route. You can acheive everything you want using Excel formulas.
To get the name of a sheet use:
=MID(CELL("filename",A1),FIND("]",CELL("filename",A1))+1,255)
Replace "A1" with a reference to the cell on the worksheet you want the name of.
Then use the Left() function to split out the "xx" from the name and then use the Right() function to split out "A"
Hope this helps.
Related
Scenario: -There are 2 sheets being compared. Range for Sheet1 is B2:B and for Sheet2 is C2:C.
Requirement:
Sheet1 B2 = Sheet2 C2
Sheet1 B3 = Sheet2 C3 and so on...
See my existing code below:
Sub MessageCode()
Dim FoundBlank1 As Range
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Sheets("Sheet2")
Dim MyRange As Range, MyCell As Range, MyRange2 As Range, MyCell2 As Range
Set MyRange = ws.Range("B2:B" & ws.Range("B" & ws.Rows.Count).End(xlUp).Row)
Set MyRange2 = ws2.Range("C2:C" & ws2.Range("C" & ws2.Rows.Count).End(xlUp).Row)
Set MyCell2 = MyRange2
For Each MyCell In MyRange
If MyCell.Value <> Worksheets("Sheet2").Range("C2").Value Then
MyCell.Copy
Worksheets("Sheet3").Select
Set FoundBlank1 = Range("A1:A1000").Find(What:="", lookat:=xlWhole)
FoundBlank1.Select
Selection.PasteSpecial xlPasteValues
ActiveCell.Offset(0, 1).Value = "Incorrect Value."
End If
Next MyCell
End Sub
I've added in some extra message box if the number of rows of sheet 1 and 2 are not the same.
Try this:
Sub Messagecode()
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim lastrow1 As Integer
Dim lastrow2 As Integer
dim lastrow3 as integer
Dim i As Integer
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
ws1.Activate
lastrow1 = Cells(Rows.Count, 2).End(xlUp).Row
ws2.Activate
lastrow2 = Cells(Rows.Count, 3).End(xlUp).Row
If lastrow1 <> lastrow2 Then
MsgBox ("number of rows in Sheet1 is not equal to number of rows in Sheet2")
End If
For i = 2 To lastrow1
If ws1.Cells(i, 2) <> ws2.Cells(i, 3) Then
ws2.Cells(i, 3).Copy
Worksheets("Sheet3").Activate
lastrow3 = Cells(Rows.Count, 1).End(xlUp).Row
Cells(lastrow3, 1).Offset(1, 0).Activate
ActiveSheet.Paste
Cells(lastrow3, 1).Offset(1, 1) = "incorrect value"
End If
ws1.Activate
Next i
End Sub
You only need to set the last row for sheet1 and sheet3. run a loop from 2 to the lastrow and compare Sheet1.columnB with Sheet2.columnC if <> then copy the value in Sheet1 to Sheet3, offset 1 cell to the right and paste your text. You add +1 to the last row in Sheet3 so you don't keep writing over the same cell...
Dim i As Long
Dim lRow As Long
lRow = Sheet1.Cells(Rows.Count, "B").End(xlUp).Row
Dim lRow3 As Long
lRow3 = Sheet3.Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To lRow
If Sheet1.Cells(i, "B").Value <> Sheet2.Cells(i, "C").Value Then
Sheet3.Cells(lRow3, "A").Value = Sheet1.Cells(i, "B").Value
Sheet3.Cells(lRow3, "A").Offset(, 1).Value = "Incorrect Value."
End If
lRow3 = lRow3 + 1
Next i
I have a workbook with 3 sheets: first one is the raw data sheet, then 2 target sheets. I would need a macro that would look at cell C in raw data sheet and based on the 2 values (YES or NO), will copy and paste the range A:Y in sheets 2, respectively 3.
Example: if on C2 in raw data sheet i have YES, copy A2:Y2 and paste into sheet 2, same range A2:Y2. If instead i have the value NO, copy A2:Y2 and paste into sheet 3.
Then go to next row and copy-paste A3:Y3 to sheet 2 if YES or A3:Y3 to sheet 3 if NO.
I wrote something that only works for the 2nd row, but i don't know how to make it loop... so basically when it passes to the next rows, it still copies the values from A2:Y2 to the target sheet, instead of copying A3:Y3, A4:Y4 etc..
Pasting my poor code below:
Sub IdentifyInfraction()
Dim rngA As Range
Dim cell As Range
Set rngA = Range("C2", Range("C65536").End(xlUp))
For Each cell In rngA
Worksheets("raw_data").Select
If cell.Value = "YES" Then
Range("A2:Y2").Copy
Worksheets("Value_YES").Select
Range("A2").PasteSpecial Paste:=xlPasteValues
ElseIf cell.Value = "NO" Then
Range("A2:Y2").Copy
Worksheets("Value_NO").Select
Range("A2").PasteSpecial Paste:=xlPasteValues
End If
Next cell
End Sub
Please help!!! :-s
Easiest solution would just be to replace the number 2 in each of your ranges to a variable which you then increment at the end your statement, before you go to the next cell.
For example:
Dim i = 2
Set rngA = Range("C2", Range("C65536").End(xlUp))
For Each cell In rngA
Worksheets("raw_data").Select
If cell.Value = "YES" Then
Range("A" & i & ":Y" & i).Copy
Worksheets("Value_YES").Select
Range("A" & i).PasteSpecial Paste:=xlPasteValues
ElseIf cell.Value = "NO" Then
Range("A" & i & ":Y" & i).Copy
Worksheets("Value_NO").Select
Range("A" & i).PasteSpecial Paste:=xlPasteValues
End If
i = i + 1
Next cell
So, originally we set i = 2, this is to go in line with your starting row of 2 mentioned in your question. Then, Range("A" & i & ":Y" & i).Copy is the same as saying Range("A2:Y2").Copy or Range("A3:Y3").Copy, etc.
This will go through any copy each row, a new row each time, and paste it to the respective row in the various sheets.
I hope this works for what you are trying to do, if not let me know.
There are a few things I'd also recommend looking into. There's a much better way to copy and paste, without going back and forward through the sheets.
ThisWorkbook.Sheets("raw_data").Rows(i).Copy Destination:=Worksheets("Value_YES").Range("A" & i)
Something like this would take the whole row from raw_data and transfer it to Value_YES. You'd have to mess around with it and change the range from Rows(i), but that's just an example.
I'd also recommend that you look into How to avoid using Select in Excel VBA to better understand why it's frowned upon to use Select and Activate in Excel VBA.
My version:
Sub GetR_Done()
Dim rng As Range, c As Range, LstRw As Long
Dim ws As Worksheet, Nr As Long, Yr As Long
Dim Ys As Worksheet, Ns As Worksheet
Set ws = Sheets("raw_data")
Set Ys = Sheets("Value_YES")
Set Ns = Sheets("Value_NO")
With ws
LstRw = .Cells(.Rows.Count, "C").End(xlUp).Row
Set rng = .Range("C2:C" & LstRw)
For Each c In rng.Cells
If c = "YES" Then
With Ys
Yr = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
.Range(.Cells(c.Row, "A"), .Cells(c.Row, "Y")).Copy Ys.Range("A" & Yr)
End If
If c = "NO" Then
With Ns
Nr = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
.Range(.Cells(c.Row, "A"), .Cells(c.Row, "Y")).Copy Ns.Range("A" & Nr)
End If
Next c
End With
End Sub
If you really require to paste values, then use this one
Sub GetR_Done()
Dim rng As Range, c As Range, LstRw As Long
Dim ws As Worksheet, Nr As Long, Yr As Long
Dim Ys As Worksheet, Ns As Worksheet
Set ws = Sheets("raw_data")
Set Ys = Sheets("Value_YES")
Set Ns = Sheets("Value_NO")
Application.ScreenUpdating = False
With ws
LstRw = .Cells(.Rows.Count, "C").End(xlUp).Row
Set rng = .Range("C2:C" & LstRw)
For Each c In rng.Cells
If c = "YES" Then
With Ys
Yr = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
.Range(.Cells(c.Row, "A"), .Cells(c.Row, "Y")).Copy
Ys.Range("A" & Yr).PasteSpecial xlPasteValues
End If
If c = "NO" Then
With Ns
Nr = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
.Range(.Cells(c.Row, "A"), .Cells(c.Row, "Y")).Copy
Ns.Range("A" & Nr).PasteSpecial xlPasteValues
End If
Next c
End With
Application.CutCopyMode = False
End Sub
you could try this:
Sub IdentifyInfraction()
Dim cell As Range
With Worksheets("raw_data") 'reference "raw data" sheet
For Each cell In .Range("C2", .cells(.Rows.Count, "C").End(xlUp)) ' loop through referenced sheet column C cells from row 2 down to last not empty one
Worksheets("Value_" & cell.Value).Range(cell.Address).Resize(, 25).Value = cell.Resize(, 25).Value 'have proper target sheet A:Y current cell row values as "raw data" sheet ones
Next
End With
End Sub
I got stuck in the below-mentioned code, what I want to do is to get the value from Range("C4:C" & LastRow) in worksheets X2 that will b changing every time and compare each value with all open workbooks name. If match found then search that value in A column of worksheet X1 and copy all those rows.
The final objective is to paste those rows into those open workbooks which have the same value. For eg: Range C4 has TW00 then the code will search workbooks which have name "TW00.xlsx" and copy all the rows from worksheet X1 which have TW00 value in column A in the worksheet named TW00.xlsx.
Dim BookNames()
ReDim BookNames(Windows.Count)
n = 1
For n = 1 To Windows.Count
BookNames(n) = Workbooks(n).Name
If Workbooks(n).Name = Workbooks("A.xlsx").Worksheets("X2").Range("C4:C" & LastRow).Value Then
Set Rng = Workbooks("A.xlsx").Worksheets("X1").Range("A2:A50000")
For Each c In Rng.Cells
If c.Value = Workbooks("A.xlsx").Worksheets("X2").Range("C4").Value Then
If Not CopyRng Is Nothing Then
Set CopyRng = Application.Union(CopyRng,
Workbooks("A.xlsx").Worksheets("X1").Rows(c))
Else
Set CopyRng = Workbooks("A.xlsx").Worksheets("X1").Rows(c)
End If
End If
Next c
CopyRng.Copy
Workbooks(n).Activate
Worksheets.Add
ActiveSheet.Name = "X1"
ActiveSheet.Paste
End If
Next n
is that code help you?
Sub test()
Dim lastRow As Long
dim sheetName as string
Dim sourceDataSheet As worksheet
Dim sourceSheetsName as worksheet
dim targetDataSheet as worksheet
Dim wkb As Variant
set sourceDataSheet = ActiveWorkbook.Worksheets("X2")
set sourceSheetsName = ActiveWorkbook.Worksheets("X1")
With sourceSheetsName
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
sheetName = .Cells(lastRow, "A")
For Each wkb In Application.Workbooks
If wkb.Name <> .Name And wkb.Name = sheetName Then
set targetDataSheet = wkb.Worksheets.Add
with sourceDataSheet
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
for i = 1 to lastRow
if .Cells(i, "A").Value = sheetName then
.Cells(i, "A").EntireRow.Copy
targetDataSheet.Cells(i, "A").PasteSpecial Paste:=xlPasteValues
end if
next i
end with
End If
Next wkb
End With
End Sub
I have two worksheets, "Signed" and "April".
I want to copy Column "Y" from "Signed" based on certain criteria into column "A" starting from the next available/blank row. ( so right under the existing data).
My criteria for column Y is that if column L = month of cell "D2" from "April" AND the year of cell "D2" from "ApriL"...( so right now D2 is 4/30/2017)..
then copy that cell in the next row of Col A of "April" and keep adding on.
my code is as follows:
Dim sourceSht As Worksheet
Dim myrange As Range
Dim DestRow As Integer
Dim ws2 As Worksheet
Dim MonthVal As String
Range("D3").Select
ActiveCell.FormulaR1C1 = "=MONTH(R[-1]C)"
Range("D3").Select
Selection.NumberFormat = "General"
MonthVal = ActiveCell.Value
Set sourceSht = ThisWorkbook.Worksheets("Signed")
Set myrange = sourceSht.Range("Y1", Range("Y" & Rows.Count).End(xlUp))
Set ws2 = Sheets("April")
DestRow = ws2.Cells(Rows.Count, "A").End(xlUp).Row + 1
For Each rw In myrange.Rows
If rw.Cells(12).Value = MonthVal Then
myrange.Value.Copy Destinations:=Sheets(ws2).Range("A" & DestRow)
End If
Next rw
Try this:
Dim sourceSht As Worksheet
Dim myrange As Range
Dim DestRow As Integer
Dim ws2 As Worksheet
Dim MonthVal As String
Dim rw As Range
Range("D3").Select
ActiveCell.FormulaR1C1 = "=MONTH(R[-1]C)"
Range("D3").Select
Selection.NumberFormat = "General"
MonthVal = ActiveCell.Value
Set sourceSht = ThisWorkbook.Worksheets("Signed")
Set myrange = sourceSht.Range("Y1:Y" & sourceSht.UsedRange.Row - 1 + sourceSht.UsedRange.Rows.Count)
Set ws2 = Sheets("April")
DestRow = ws2.Cells(Rows.Count, "A").End(xlUp).Row ' + 1
For Each rw In myrange '.Rows
If sourceSht.Cells(rw.Row, 12).Value = MonthVal Then
DestRow = DestRow + 1
rw.Copy Destination:=Sheets("April").Range("A" & DestRow)
End If
Next rw
Edit: fixed a potential loophole at line 15 (from Set myrange = sourceSht.Range("Y1:y" & sourceSht.UsedRange.Rows.Count) to Set myrange = sourceSht.Range("Y1:Y" & sourceSht.UsedRange.Row - 1 + sourceSht.UsedRange.Rows.Count)), in case there are unused rows at the top.
I want a code that doing the following:
if the last 5 characters of the text value in the cell in column E is “(UK)” then the macro copies the range consisting of 4 cells in columns B,C,D,E in the same row and pastes below the last non-empty row in the worksheet “Sheet 1” in the same columns (so all ranges B-E with “(UK)” must be transferred to the sheet “Sheet1”);
I am just posting my code. Hope #Jonathan will learn it.
Sub CopyC()
Dim wb As Workbook
Dim ws As Worksheet
Dim sheet1lastrow As Long
Dim lastrow As Long
Set wb = ThisWorkbook
Set ws = wb.Worksheets("sheet1")
lastrow = ActiveSheet.Range("E" & Rows.Count).End(xlUp).Row
sheet1lastrow = ws.Range("E" & Rows.Count).End(xlUp).Row
For i = 1 To lastrow
If Right(ActiveSheet.Cells(i, 5).Value, 5) = "(UK)" Then
ActiveSheet.Range(Cells(i, 2), Cells(i, 5)).Copy
ws.Cells(sheet1lastrow + 1, 2).PasteSpecial xlValues
Application.CutCopyMode = False
Application.CutCopyMode = True
End If
Next
End Sub