Copy a Worksheet if the Cell Value equals a certain string using row and column indexes - excel

The purpose of this is to find the column who has the header "Type Test" and loop through that column, in this case B to find all unique value cells. If the string in column B is unique and does not replace, I need it to make a copy of the worksheet whose name matches the trial name in column A. So for Test 1 who has a row index of 3 and a column index of 2, will make a copy of the worksheet in the current workbook called "DEF" and rename the copy to be "Test 1"
For example here is my data
A B
Trial Type_Test
DEF Test 1
ABC Test 3
ABC Test 10
DEF Test 14
ABC Test 10
However, I dont want to make a copy of the sheet ABC if the column B values repeat for column A, so since rows 3 and 5 are the same, I only want to make copies of ABC sheet twice, once for row 2 and once for row 3. Row 5 can be ignored since it is the same as row 3.
I have written a code that does the first part regarding make a sheet and renaming it, I just cant get the copy the other worksheet part.
Public Sub Main()
Dim srtsht As Variant, sysnum As Variant, arr As Variant, partnum As Variant
Dim wsh As Worksheet
srtsht = Sheets("Sheet1").Range("E2:E15")
With CreateObject("scripting.dictionary") ' store data in array where each item is associated with a unique key
For Each sysnum In srtsht
arr = .Item(sysnum)
Next sysnum
For Each value In .Keys
On Error Resume Next
If value <> "" Then
Set wsh = Nothing ' clear the variable wsh
Set wsh = Worksheets(CStr(value)) ' try to set wsh to the sheet with Value as name
On Error GoTo 0
If wsh Is Nothing Then
Call position
If Worksheets("Sheet1").Cells(A_row,A_col).Value = "ABC" Then
Worksheets("ABC").Copy After:=ActiveSheet
wsh = Worksheets("Sheet1").Cells(A_row,A_col).Values
Worksheets("ABC (2)").name = wsh
wsh.name = CStr(Value)
End If
Else
MsgBox "Sheet" & Values & "already exists.", vbInformation
End If
End If
Next Value
End With
End Sub
Sub position ()
Dim syswaivernum As Range, partnumber As Range
For Each syswaivernum In Worksheets("Sheet1").Range("A1:Z20")
If syswaivernum.value = "Number(s)" Then
sysnumcol = syswaivernum.Column
sysnumrow = syswaivernum.Row
End If
Next syswaivernum
For Each partnumber In Worksheets("Sheet1").Range("A1:Z20")
If partnumber.value = "Part" Then
A_col = partnumber.Column
A_row = partnumber.Row
End If
Next partnumber
End Sub

Try this - see comments inline:
Public Sub Main()
Dim wb As Workbook, tst As String, wsName As String
Dim c As Range, ws As Worksheet, dict As Object
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1")
Set dict = CreateObject("scripting.dictionary")
For Each c In ws.Range("E2:E15").Cells
tst = c.Value
If Not dict.exists(tst) Then 'first time seeing this value?
dict.Add tst, True '###
If Not SheetExists(tst) Then
wsName = c.EntireRow.Columns("A").Value 'sheet to be copied
If SheetExists(wsName) Then 'if there's a sheet for wsName
wb.Worksheets(wsName).Copy After:=ws 'copy the sheet
wb.Worksheets(ws.Index + 1).Name = tst '### rename the copy
End If
Else
MsgBox "Sheet '" & wsName & "' already exists"
End If
End If
Next c
End Sub
'Does a sheet named `SheetName` exist?
' Defaults to checking `ThisWorkbook` if `wb` is not specified
Function SheetExists(SheetName As String, _
Optional wb As Excel.Workbook) As Boolean
If wb Is Nothing Then Set wb = ThisWorkbook
On Error Resume Next
SheetExists = Not wb.Sheets(SheetName) Is Nothing
End Function

Related

Pasting specific data on a new sheet with macro

I have a hospital spreadsheet with data, where the data is organised depending on age, sex, Health Authority etc. Like this:
Where "sha" means the Health Authority, and each number corresponds to a certain one.
1-Norfolk, Suffolk and Cambridgeshire
2-Bedforshire & Hertfordshire
and so on until Health Authority number 28
I am creating a macro that opens a new sheet, and I need to only paste the data of the patients from a certain Health authority previously selected from a drop-down box.
I have already created the macro that creates the new sheet (i'll paste the code here), but now I need to paste all the data of the patients only if they belong to the health authority selected from the drop-down box.
This is my code so far:
Option Explicit
Sub createsheet()
Dim sName As String, ws As Worksheet
sName = Sheets("user").Range("M42").Value
' check if already exists
On Error Resume Next
Set ws = Sheets(sName)
On Error GoTo 0
If ws Is Nothing Then
' ok add
Set ws = Sheets.Add(after:=Sheets(Sheets.Count))
ws.Name = sName
MsgBox "Sheet created : " & ws.Name, vbInformation
Else
' exists
MsgBox "Sheet '" & sName & "' already exists", vbCritical, "Error"
End If
End Sub
You can call this sub from your sub like:
Transfer_to_NewSheet ws, SHA
Where SHA is the SHA number from whatever drop down you're using.
I'm sure you can figure out how to do that.
Also remember to change:
Set Master = Worksheets("Main")
to whatever your data sheet is called.
Sub Transfer_to_NewSheet(WS As Worksheet, SHA)
Dim Master As Worksheet
Dim DataRG As Range
Dim InArray
Dim OutArray
Dim I As Long
Dim Y As Long
Dim X As Long
Dim W As Long
Dim lRow As Long
Dim lCol As Long
Dim SHAcol As Long
' Or whatever your master sheet is called
Set Master = Worksheets("Main")
With Master
lCol = .Range("ZZ1").End(xlToLeft).Column
lRow = .Range("A" & Rows.Count).End(xlUp).Row
SHAcol = .Range("A1").Resize(1, lCol).Find(What:="sha", LookIn:=xlValues, LookAt:=xlWhole).Column
Set DataRG = .Range("A1").Resize(lRow, lCol)
End With
InArray = DataRG
ReDim OutArray(1 To lRow, 1 To lCol)
Y = 1
For I = 1 To UBound(InArray, 1)
If InArray(I, SHAcol) = SHA Or I = 1 Then
For X = 1 To UBound(InArray, 2)
OutArray(Y, X) = InArray(I, X)
Next X
Y = Y + 1
End If
Next I
WS.Range("A1").Resize(lRow, lCol) = OutArray
End Sub
This is the Data I used to test:
This is the output I get from SHA = 12
And this is the sub I was using to call it, just for reference. don't use it.
Sub CallWSxfer()
Dim SHA As Long
' Or pull it from whatever drop down you're using...
SHA = InputBox("Enter SHA Number:", "SHA to New Sheet", "01")
Transfer_to_NewSheet Sheet4, SHA
End Sub
you can use AutoFilter() method of Range object:
assuming:
data have headers in row 10 from column 1 rightwards and don't have blank rows/columns in between
the searched SHA will always be found in data column F
you could place this snippet right after your MsgBox "Sheet created : " & ws.Name, vbInformation code line
With Sheets("data")
With .Range("A10").CurrentRegion
.AutoFilter field:=6, Criteria1:=sName
.SpecialCells(XlCellType.xlCellTypeVisible).Copy ws.Range("A1")
End With
.AutoFilterMode = False
End With

Date loop overflow

I have two dates, both in a named cell.
Range("NewStartDate").Value = 24/07/2022 and Range("FinishDate").Value = 31/12/2023
I need all columns to have heading which is a date 7 days after previous column, i.e.
A1 is NewStartDate, B1 is NewStartDate+7, C1 is NewStartDate + 7*2, etc. and it will end once we reach the FinishDate.
I created this loop
Sub FillInDates()
Dim i as Integer, d as Date, x as Date
Range("NewStartDate").Value = "24/07/2022"
Range("FinishDate").Value = "31/12/2023"
d = Range("NewStartDate").Value
i = 1
Do While x < FinishDate
Range("NewStartDate").Offset(0, i).Value = DateSerial(Year(d), Month(d), Day(d) + (7*i)
x = Range("NewStartDate").Offset(0, i).Value
i = i + 1
Loop
End Sub
It fills in the following column with the correct next week, however it never stops and I get an overflow error. Why is it not able to stop once we get past end date??
I can't reproduce your error but I can recommend using arrays instead of interacting with the spreadsheet one cell at a time - it is much faster.
Your code could look like this:
Sub FillInDates()
Dim StartDate As Date
Dim FinishDate As Date
StartDate = Range("NewStartDate")
FinishDate = Range("FinishDate")
Dim i As Long
Dim DateArray As Variant
ReDim DateArray(1 To 1, 1 To Int((FinishDate - StartDate) / 7)) As Variant
For i = 1 To UBound(DateArray, 2)
DateArray(1, i) = StartDate + i * 7
Next i
Range("NewStartDate").Offset(0, 1).Resize(1, UBound(DateArray, 2)) = DateArray
End Sub
Create a Sequence Using a Dictionary
Since things are not all clear (to me), I've produced this little investigation.
The named ranges (cells) are named ranges of workbook scope in the workbook containing this code (ThisWorkbook).
The worksheet to be written to is the active sheet which can be a worksheet in another workbook.
It looks preferable to use a For...Next loop with Step to loop over the range of the dates.
Since the results are unique, I've pretended that I don't know how to calculate the number of the resulting dates and chose to write them to the keys of a dictionary which conveniently are already 'stored' in a 1D array (one row) for easy copying to the worksheet.
Option Explicit
Sub FillInDates()
' Reference the source workbook ('swb'), the workbook containing
' the named ranges (cells).
Dim swb As Workbook: Set swb = ThisWorkbook ' workbook containing this code
' Attempt to reference the active sheet ('dsh').
Dim dsh As Object: Set dsh = ActiveSheet
' Validate the active sheet.
If dsh Is Nothing Then
MsgBox "No visible workbooks open.", vbCritical
Exit Sub
End If
' Check if the active sheet is a worksheet, the destination worksheet.
If dsh.Type <> xlWorksheet Then
MsgBox "No worksheet selected.", vbCritical
Exit Sub
End If
' If the active workbook is not the workbook containing this code,
' reference it ('dwb') and activate the workbook containing this code
' ('swb') to be able to use the workbook-scope named ranges (cells).
Dim dwb As Workbook
If Not swb Is ActiveWorkbook Then
Set dwb = ActiveWorkbook
swb.Activate
End If
' Just an example, this doesn't belong in the code.
Range("NewStartDate").Value = #12/31/2023#
Range("FinishDate").Value = #7/24/2022#
' Validate the contents of the named ranges (cells)
' and write them (the dates) to variables ('nDate','fDate')
Dim cValue As Variant
cValue = Range("NewStartDate").Value
If Not IsDate(cValue) Then
MsgBox "'" & CStr(cValue) & "' is not a date.", vbCritical
Exit Sub
End If
Dim nDate As Date: nDate = cValue
cValue = Range("FinishDate").Value
If Not IsDate(cValue) Then
MsgBox "'" & CStr(cValue) & "' is not a date.", vbCritical
Exit Sub
End If
Dim fDate As Date: fDate = cValue
If nDate > fDate Then
MsgBox "The new start date (" & CStr(nDate) _
& ") is greater than the finish date (" & CStr(fDate) & ").", _
vbCritical
Exit Sub
End If
' If it was not the workbook containing this code,
' activate the initially active workbook, the destination workbook.
If Not dwb Is Nothing Then dwb.Activate
' Write the dates to the 'keys' of a dictionary ('dict').
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim d As Date
For d = nDate To fDate Step 7
dict(d) = Empty
Next d
' Write the dates from the dictionary to the destination worksheet.
Dim cc As Long: cc = dict.Count
' Reference the destination range.
With dsh.Range("A1").Resize(, cc)
' Write the values from the 'keys' of the dictionary
' to the destination range.
.Value = dict.keys
' Format copied data.
.Font.Bold = True
.EntireColumn.AutoFit
' Clear to the right.
With .Resize(, dsh.Columns.Count - .Column - cc + 1).Offset(, cc)
.Clear
.ColumnWidth = 8.43
End With
End With
' Inform.
MsgBox "Dates filled in.", vbInformation
End Sub

How to copy row from Excel sheet and paste it in another workbook in a specific row

In Workbook 1, I have a spreadsheet that tracks the inventory of meat products.
Row 1 is used for the column names: "Parcel Tracking Number" in column A and other data related to the parcel in the other columns (Such as "Date of export", "Weight" and "Content" among other things).
Column I describes the parcel's "Content" and these parcels all contain "Meat".
The rows of information in this spreadsheet have been copied from Workbook 2 which contains parcels that contain "Meat", "Cheese", "Milk" and "Eggs" in column I.
Both workbooks have the same columns names in row 1.
In workbook 1, I update the data on some of the rows and I want the change to be applied in Workbook 2 by copying workbook 1 rows and pasting them in Workbook 2 in the rows where the "Parcel Tracking Number" in column A matches.
So far, I have the code to copy all the "Meat" parcel rows from Workbook 2 and paste them in Workbook 1 but now I need help with this new situation.
The program is executed by opening Workbook 2 and pressing a command button which opens workbook 1 and starts copying the rows to the Meat worksheet.
Here it is:
Private Sub CommandButton1_Click()
Application.ScreenUpdating = False ' Screen Update application turned off in order to make program run faster
Dim y As Workbook '
Dim sh As Worksheet '
Set y = Workbooks.Open("\\SCF1\USERS-D\Robert\My Documents\Excel VBA code\Meat.xlsx") '
a = ThisWorkbook.Worksheets("Products").Cells(Rows.Count, 1).End(xlUp).Row
Set sh = Workbooks("Meat.xlsx").Worksheets("Meat")
With ThisWorkbook.Worksheets("Products")
For i = 2 To a ' value ''i'' is the column number
If ThisWorkbook.Worksheets("Products").Cells(i, 9).Value Like "*Meat*" And IsError(Application.Match(.Cells(i, "A").Value, sh.Columns("A"), 0)) Then ' this sets the condition for which the data can only be copied if the row has '' Meat '' included in the 9th column (substance) and if the row is not already copied in the Meat worksheet.
ThisWorkbook.Worksheets("Products ").Rows(i).Copy
Workbooks("Meat.xlsx").Worksheets("Meat").Activate
b = Workbooks("Meat.xlsx").Worksheets("Meat ").Cells(Rows.Count, 1).End(xlUp).Row
Workbooks("Meat.xlsx").Worksheets("Meat").Cells(b + 1, 1).Select
ActiveSheet.Paste
ThisWorkbook.Worksheets("Products").Activate
End If
Next
On Error Resume Next '1004 error kept appearing so this function allows us to continue to next step without error appearing
ThisWorkbook.Worksheets("Products").Cells(1, 1).Select
End With
MsgBox "All rows from Products worksheet have been copied."
Application.ScreenUpdating = True
End Sub
Any help is greatly appreciated. Thanks.
Use Find to check if Tracking Number exists and to locate row when transferring data back to Products.
Option Explicit
Sub CommandButton1_Click()
' update meat
Const PATH = "\\SCF1\USERS-D\Robert\My Documents\Excel VBA code\"
Const WB_NAME = "Meat.xlsx"
Dim wb As Workbook, ws As Worksheet, iLastRow As Long, iRow As Long
Dim wbTarget As Workbook, wsTarget As Worksheet, iTargetRow As Long
Set wbTarget = Workbooks.Open(PATH & WB_NAME)
Set wsTarget = wbTarget.Sheets("Meat")
iTargetRow = wsTarget.Cells(Rows.count, 1).End(xlUp).Row + 1
Set wb = ThisWorkbook
Set ws = wb.Sheets("Products")
iLastRow = ws.Cells(Rows.count, 1).End(xlUp).Row
Dim sContent As String, sTrackId As String
Dim res As Variant, count As Long
'Application.ScreenUpdating = False
count = 0
For iRow = 2 To iLastRow
sTrackId = ws.Cells(iRow, "A")
sContent = ws.Cells(iRow, "I")
If LCase(sContent) Like "*meat*" Then
' check not already on sheet
Set res = wsTarget.Range("A:A").Find(sTrackId)
If (res Is Nothing) Then
ws.Rows(iRow).Copy wsTarget.Cells(iTargetRow, 1)
iTargetRow = iTargetRow + 1
count = count + 1
End If
End If
Next
'wbTarget.Save
'wbTarget.Close
MsgBox count & " rows inserted from Products worksheet."
'Application.ScreenUpdating = True
End Sub
Sub CommandButton2_Click()
' update product
Const PATH = "\\SCF1\USERS-D\Robert\My Documents\Excel VBA code\"
Const WB_NAME = "Meat.xlsx"
Dim wb As Workbook, ws As Worksheet, iRow As Long
Dim wbSource As Workbook, wsSource As Worksheet, iLastSourceRow As Long
Set wbSource = Workbooks.Open(PATH & WB_NAME, False, True) 'no link update, read-only
Set wsSource = wbSource.Sheets("Meat")
iLastSourceRow = wsSource.Cells(Rows.count, 1).End(xlUp).Row + 1
Set wb = ThisWorkbook
Set ws = wb.Sheets("Products")
Dim sTrackId As String
Dim res As Variant, count As Long
'Application.ScreenUpdating = False
count = 0
For iRow = 2 To iLastSourceRow
sTrackId = wsSource.Cells(iRow, "A")
' find row on product sheet
Set res = ws.Range("A:A").Find(sTrackId)
If (res Is Nothing) Then
MsgBox "Could not update " & sTrackId, vbExclamation
Else
wsSource.Rows(iRow).Copy ws.Cells(res.Row, 1)
count = count + 1
End If
Next
wbSource.Close
MsgBox count & " rows updated from Meat workbook."
'Application.ScreenUpdating = True
End Sub

Extracting Data from Excel Database

I've got a database with a long list of names, and unique values associated with the names. What I want to do is create one worksheet for each individual, and then copy only their data to a specified range in their worksheet, then proceed to the next individual, copy their data to their worksheet etc.
Here is a link to an example worksheet (in google docs form, note - I am actually using Excel 2010, not google docs).
I've been able to create all the worksheets through using the following code in a new sheet I called "Employee". All I did to this sheet was remove the duplicate name values so I could have a list of all the names for the worksheets.
Any help is much appreciated. Thanks in advance.
Sub CreateSheetsFromAList()
Dim nameSource As String 'sheet name where to read names
Dim nameColumn As String 'column where the names are located
Dim nameStartRow As Long 'row from where name starts
Dim nameEndRow As Long 'row where name ends
Dim employeeName As String 'employee name
Dim newSheet As Worksheet
nameSource = "Employee"
nameColumn = "A"
nameStartRow = 1
'find the last cell in use
nameEndRow = Sheets(nameSource).Cells(Rows.Count, nameColumn).End(xlUp).Row
'loop till last row
Do While (nameStartRow <= nameEndRow)
'get the name
employeeName = Sheets(nameSource).Cells(nameStartRow, nameColumn)
'remove any white space
employeeName = Trim(employeeName)
' if name is not equal to ""
If (employeeName <> vbNullString) Then
On Error Resume Next 'do not throw error
Err.Clear 'clear any existing error
'if sheet name is not present this will cause error that we are going to leverage
Sheets(employeeName).Name = employeeName
If (Err.Number > 0) Then
'sheet was not there, so it create error, so we can create this sheet
Err.Clear
On Error GoTo -1 'disable exception so to reuse in loop
'add new sheet
Set newSheet = Sheets.Add(After:=Sheets(Sheets.Count))
'rename sheet
newSheet.Name = employeeName
'paste training material
Sheets(employeeName).Cells(1, "A").PasteSpecial
Application.CutCopyMode = False
End If
End If
nameStartRow = nameStartRow + 1 'increment row
Loop
End Sub
Bare bones approach - could be optimized for better performance, but it will do the job.
Sub SplitToSheets()
Dim c As Range, ws As Worksheet, rngNames
With ThisWorkbook.Sheets("EmployeeData")
Set rngNames = .Range(.Range("A1"), .Cells(Rows.Count, 1).End(xlUp))
End With
For Each c In rngNames.Cells
Set ws = GetSheet(ThisWorkbook, c.Value)
c.EntireRow.Copy ws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
Next c
End Sub
Function GetSheet(wb As Workbook, wsName As String, _
Optional CreateIfMissing As Boolean = True) As Worksheet
Dim ws As Worksheet
On Error Resume Next
Set ws = wb.Sheets(wsName)
On Error GoTo 0
If ws Is Nothing And CreateIfMissing Then
Set ws = wb.Sheets.Add(after:=wb.Sheets(wb.Sheets.Count))
ws.Name = wsName
End If
Set GetSheet = ws
End Function

merge multiple worksheets into one

I'm trying to merge multiple worksheets into one summary sheet.
Each Worksheet has the name 'Table #number', for example Table 1, Table 2 etc. The layout of each sheet is identical. Data range is columns A1 : N13.
This function doesn't work: =SUM('Table 1':'Table 25'!$A$1:$N$13).
How do I use VBA to amalgamate this data?
Sub MergeSheet()
'Declaring the Variables
Dim LastRow, ShtCnt As Integer
Dim ShtName As String
Dim NewSht As Worksheet
'Assinging a Sheet Name by UserInput
ShtName:
ShtName = InputBox("Enter the Sheet Name you want to create", "Merge Sheet", "Master Sheet")
'Count of Total Worksheet in the present workbook
ShtCnt = Sheets.Count
'Using For Loop check if the worksheet exists
For i = 1 To ShtCnt
If Sheets(i).Name = ShtName Then
MsgBox "Sheet already Exists", , "Merge Sheet"
GoTo ShtName
End If
Next i
'Create a New Sheet
Worksheets.Add.Name = ShtName
'Assigning NewSht as Current Sheet
Set NewSht = ActiveSheet
'Moving Worksheet to the beginning of this workbook
NewSht.Move before:=Worksheets(1)
'Copying all the data to the New Sheet Using For Loop
For i = 2 To ShtCnt + 1
'If i=2 Then copy all the data from the second sheet including header.
If i = 2 Then
Sheets(i).UsedRange.Copy NewSht.Cells(1, 1)
Else
'If i is grater than 2 then copy all the data excluding Header(1st Row).
Sheets(i).UsedRange.Offset(1, 0).Resize(Sheets(i).UsedRange.Rows.Count - 1, Sheets(i).UsedRange.Columns.Count).Copy NewSht.Cells(LastRow + 1, 1)
End If
LastRow = NewSht.Cells.SpecialCells(xlCellTypeLastCell).Row
Next i
'Displaying the Message after copying data successfully
MsgBox "Data has been copied to " & ShtName, , "Merge Sheet"
End Sub
This is a simplified example:
Option Explicit
Sub amalgamateData()
'initialise result variable
Dim myResult As Double
myResult = 0
'loop through sheets to get the sum
Dim wks As Excel.Worksheet 'loop control variable
For Each wks In Excel.ThisWorkbook.Worksheets
If Left(wks.Name, 5) = "Table" Then ' only the "Table" sheets
With wks
Dim rngTarget As Range
myResult = myResult + Excel.Application.WorksheetFunction.Sum(.Range("A1:N13"))
End With
End If
Next
'add result to sheet "Result"
Excel.ThisWorkbook.Sheets("Result").Range("A1") = myResult
End Sub
My starting point was this SO Post: how-to-merge-data-from-multiple-sheets
As Siddharth saud - there loads of references for you on SO HERE IS A SEARCH FOR YOU ... CHECK OUT WHAT IS IN THE BOX IN THE TOP RIGHT OF THE SCREEN

Resources