Find If Value Exists on other Worksheet (Excel) - vba

I have a macro tied to a button click event on my Excel worksheet. When this event fires, I need to see if the value on my worksheet FeedSampleForm Range("A5:B5").Value exists anywhere in column B of my other worksheet FeedSamples.
Can anyone assist me with this? I'm barely a user when it comes to Excel, and this is my first time "Developing" with it.
EDIT:
Current Code below. This is for different save procedures depending on if saving a new record or saving after editing a previously created record.
For Sample Data, say I'm looking for "FeedSampleForm".Range("A5:B5").Value which is "SR0238", I need to see if "SR0238" exists in column B on "FeedSamples" worksheet, currently containing "SR0237" - "SR0252". If it doesn't exist, I can use same code as my Add Record functionality, but if it does, I have to write to that exact row when saving.
Sub SaveInspection()
If modeAdd = True Then
'Labeler Reg. No.
Worksheets("FeedSamples").Range("A1").End(xlDown).Offset(1, 0).value = Range("L3:M3").value
'Feed Report No.
Worksheets("FeedSamples").Range("B1").End(xlDown).Offset(1, 0).value = Range("A5:B5").value
'Product No. / Class No.
Worksheets("FeedSamples").Range("C1").End(xlDown).Offset(1, 0).value = Range("C5").value
Worksheets("FeedSamples").Range("E1").End(xlDown).Offset(1, 0).value = Range("D5").value
Worksheets("FeedSamples").Range("F1").End(xlDown).Offset(1, 0).value = Range("E5").value
'Description No.
Worksheets("FeedSamples").Range("H5").End(xlDown).Offset(1, 0).value = Range("F5").value
Worksheets("FeedSamples").Range("I5").End(xlDown).Offset(1, 0).value = Range("G5").value
Worksheets("FeedSamples").Range("J5").End(xlDown).Offset(1, 0).value = Range("H5").value
Worksheets("FeedSamples").Range("K5").End(xlDown).Offset(1, 0).value = Range("I5").value
'Possessor No.
Worksheets("FeedSamples").Range("L1").End(xlDown).Offset(1, 0).value = Range("J5:K5").value
'Date
Worksheets("FeedSamples").Range("M").End(xlDown).Offset(1, 0).value = Range("L5:M5").value
'Possessor Name
Worksheets("FeedSamples").Range("AB1").End(xlDown).Offset(1, 0).value = Range("A8:F8").value
'Possessor Address
Worksheets("FeedSamples").Range("AC1").End(xlDown).Offset(1, 0).value = Range("A10:F10").value
'Possessor City/St
Worksheets("FeedSamples").Range("AD1").End(xlDown).Offset(1, 0).value = Range("A11:E11").value
'POssessor Zipcode
Worksheets("FeedSamples").Range("AE1").End(xlDown).Offset(1, 0).value = Range("F11").value
'Labeler Name
Worksheets("FeedSamples").Range("AF1").End(xlDown).Offset(1, 0).value = Range("H8:M8").value
'Labeler Address
Worksheets("FeedSamples").Range("AG1").End(xlDown).Offset(1, 0).value = Range("H10:M10").value
'Labeler City/St
Worksheets("FeedSamples").Range("AH1").End(xlDown).Offset(1, 0).value = Range("H11:L11").value
'Labeler Zipcode
Worksheets("FeedSamples").Range("AI1").End(xlDown).Offset(1, 0).value = Range("M11").value
'Product Name
Worksheets("FeedSamples").Range("AJ1").End(xlDown).Offset(1, 0).value = Range("A13:I13").value
'1. Med
Worksheets("FeedSamples").Range("AK1").End(xlDown).Offset(1, 0).value = Range("J13:K13").value
'2. Non-Med
Worksheets("FeedSamples").Range("AL1").End(xlDown).Offset(1, 0).value = Range("L13:M13").value
'No. Bags/Loc. Sampled
'Total No. Guarantees
Worksheets("FeedSamples").Range("P").End(xlDown).Offset(1, 0).value = Range("C15:E15").value
'Flag Sample
Worksheets("FeedSamples").Range("Q").End(xlDown).Offset(1, 0).value = Range("F15:G15").value
'Sample Def.
Worksheets("FeedSamples").Range("R").End(xlDown).Offset(1, 0).value = Range("H15:I15").value
'Compliance
'Duplicate
'Bag Tag Mark or Code
Worksheets("FeedSamples").Range("U").End(xlDown).Offset(1, 0).value = Range("A17:H17").value
'On Hand
Worksheets("FeedSamples").Range("V").End(xlDown).Offset(1, 0).value = Range("I17:K17").value
'Approx. Wt/Lbs
Worksheets("FeedSamples").Range("W").End(xlDown).Offset(1, 0).value = Range("L17:M17").value
'Remarks
Worksheets("FeedSamples").Range("AA").End(xlDown).Offset(1, 0).value = Range("A19:M19").value
'Sample Taken From
'Sample Method
'Form
'Probe Size
'Product No./Class No.
Worksheets("FeedSamples").Range("D").End(xlDown).Offset(1, 0).value = Range("A23:C23").value
modeAdd = False
End If
If modeEdit = True Then
'find the record in "datatable" and save over fields.
Dim result As Variant
Dim sheet As Worksheet
Set sheet = ActiveWorkbook.Sheets("FeedSamples")
'Range("O3").Formula = "=IF(ISERROR(MATCH(Range("A5:B5").Value, sheet.Range("B:B"), 0)), "Not Found", "Value found on row " & MATCH(Range("A5:B5").Value, sheet.Range("B:B"), 0))"
'Range("O3").Formula = "=IF(ISERROR(MATCH(12345,A:A,0)),"Not Found","Value found on row " & MATCH(12345,A:A,0)))"
result = Application.WorksheetFunction.VLookup(Range("A5:B5").value, sheet.Range("B2:B25000"), 2, False)
'Throws Object Required Error
MsgBox result
modeEdit = False
allowNav = True
End If
End Sub

A very easy way is to declare the range that you want to search in and the value that you want to find.
Sub findValue()
Dim xlRange As Range
Dim xlCell As Range
Dim xlSheet As Worksheet
Dim valueToFind
valueToFind = "MyValue"
Set xlSheet = ActiveWorkbook.Worksheets("Sheet2")
Set xlRange = xlSheet.Range("B1:B10")
For Each xlCell In xlRange
If xlCell.Value = valueToFind Then
'Do Something
End If
Next xlCell
End Sub
I'm assuming that your range of ("A5:B5") is a merged cell because you indicated that it contained a single value. Merged cells can just be referenced by the "top left" cell within the merge (or at least that's how I think of it). So your merged range of ("A5:B5") can be referred to as just ("A5"). Anyway, here is a modified version of the method above that is more suited for your needs.
Sub findValue(ByVal valueToFind As String)
Dim xlRange As Range
Dim xlCell As Range
Dim xlFormSheet As Worksheet
Dim xlSamplesSheet As Worksheet
Dim iLastRow As Integer
Dim iRow As Integer
Dim bFound As Boolean
bFound = False
Set xlFormSheet = ActiveWorkbook.Worksheets("FeedSampleForm")
Set xlSamplesSheet = ActiveWorkbook.Worksheets("FeedSamples")
iLastRow = xlSamplesSheet.Range("B1").End(xlDown).Row
Set xlRange = xlsamplesheet.Range("B1:B" & iLastRow)
For Each xlCell In xlRange
If xlCell.value = valueToFind Then
bFound = True '<-- The value was found
iRow = xlCell.Row '<-- Here is the row that the value was found on
End If
If bFound Then Exit For '<-- Optional: Exit the for loop once the value is found the first time
Next xlCell
End Sub

Related

Pasting multiple ranges to another sheet in vba

I'd like the code to paste 'cashb' underneath 'rngcel', but every time
I run the code 'cashb''s value appears above 'rngCel'.value. Rngcell's range is from A2:A34, I'd like 'Cashb' to appear right below it at A35. I tried putting 'A35' in the
range but it does not work.
This is the code that I want to appear below rngcel.value.
Sheets(" Price").Range("A35").Resize(Cashb.Rows.Count).Value = Cashb.Value
I'd also like to return the column that's 5 columns to the right of "cashb"range
I appreciate any help that I receive.
This is the code that I have.Thanks in advance.
Sub liveP()
Application.ScreenUpdating = False
Dim rngTicker As Range
Dim rngCel As Range
Dim Cashb As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets.Add(After:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = "Live"
Set rngTicker = Worksheets("prices").Range("H16:H200")
Set Cashb = Sheets("prices").Range("cashbalances")
For Each rngCel In rngTicker
If rngCel.Font.ColorIndex = 33 Then
Worksheets("Live").Cells(Rows.Count, 1).End(xlUp).offset(1).Resize(1, 2).Value = Array(rngCel.offset(, "-7").Value, rngCel.Value) ' this is range cell value'
WorkSheets("Live").Range("A35").Resize(Cashb.Rows.Count).Value = Cashb.Value.offset ' this is the value I'd like to appear under rngcel value
'New data that im posting on the Live sheet'
Sheets("Live").Range("C2:H33").Formula = "=($B2 +$C5)"
Sheets("Live").Range("A1") = "Header1"
Sheets("Live").Range("B1") = "Header2"
Sheets("Live").Range("C1") = "Header3"
Sheets("Live").Range("D1") = "Header4"
Sheets("Live").Range("E1") = "Header5"
Sheets("Live").Range("F1") = "Header6"
End If
Next
Application.ScreenUpdating = True
End Sub
Try This
Sub liveP()
Application.ScreenUpdating = False
Dim rngTicker As Range
Dim rngCel As Variant 'used in for each this should be variant
Dim Cashb As Range
Dim ws As Worksheet
Dim LastRow As Long 'dimensioned variable for the last row
Dim CashbRows As Long 'dimensioned variable for Cashb rows
Set ws = ThisWorkbook.Sheets.Add(After:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = "Live"
Set rngTicker = Worksheets("prices").Range("H16:H200")
Set Cashb = Sheets("prices").Range("cashbalances")
'Assuming "cashbalances" is a named range in the worksheet
CashbRows = Cashb.Rows.Count
For Each rngCel In rngTicker
If rngCel.Font.ColorIndex = 33 Then
With Worksheets("Live")
LastRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1 'set lastrow variable
.Cells(LastRow, 1) = rngCel.Offset(0, -7).Value 'putting value 7 columns before into live worksheet column A
.Cells(LastRow, 2) = rngCel.Value 'putting value into live worksheet column B
.Range(.Cells(35, 1), .Cells(35 + CashbRows, 1)) = Cashb.Offset(, 5).Value 'im not really sure if this line is going to work at all
'New data that im posting on the Live sheet'
.Range("C2:H33").Formula = "=($B2 +$C5)"
.Range("A1") = "Header1"
.Range("B1") = "Header2"
.Range("C1") = "Header3"
.Range("D1") = "Header4"
.Range("E1") = "Header5"
.Range("F1") = "Header6"
End With
End If
Next
Application.ScreenUpdating = True
End Sub
Modifications:
rngCel is now a variant not a range
Using a LastRow Variable to get away from offset
Removed the array when placing data into "LIVE" because why not
CashbRows will now only be calculated one time before the loop. Saving time
The With Worksheets("Live") statement is a time saving measure.
You were calling A35 as a range, which it is not, then resizing to a range maybe? Hard to know when I cant tell what "cashbalances" is. If "cashbalances is only 1 row or may ever be 1 row, then you will need to add an If Then Else control to handle it.
Also A35 gets overwritten every single loop... so not sure what you want to do there.
I hope I was able to understand your questions well enough to get you going in the right direction.
EDIT
Stop treating "cashbalances" as a named range. I believe VBA is hanging onto the original row numbers of the range, similar to how Variant arrays start at 1 when assigned as I do in the following. It does not look like you are modifying "cashbalances" so create a variant array before the loop but after CashbRows.
EXAMPLE:
Dim CB() as variant, j as long
with sheets("PUT THE SHEET NAME OR INDEX HERE")
CB = .range(.cells(1,6), .cells(CashbRows,6)).value 'address to whatever .offset(,5) is
'i assumed cashb was in column A
Instead of .Range(.Cells(35, 1), .Cells(35 + CashbRows, 1)) = Cashb.Offset(, 5).Value Use:
For j = 1 to CashbRows
.cells(34 + j, 1) = CB(j)
Next j

How can I reference a sheet that is named by the first part of the macro?

I'm trying to write a macro that let's the user create a new sheet, name it, and then based on what option they've chosen, will paste a certain text in that new sheet. But my searching and piecing together only got me so far.
Sub AddNameNewSheet1()
Dim Newname As String
Newname = InputBox("Name for new account?")
If Newname <> "" Then
Sheets.Add Type:=xlWorksheet
ActiveSheet.Name = Newname
Range("D1") = Newname
End If
Dim LR As Long, i As Long
With Sheets("Start Page")
LR = .Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To LR
With .Range("A" & i)
If .Value = "Debit" Then
Sheets("Account Styles").Range("A1:G3").Copy Destination:=Sheets("").Range("A1:G3")
ElseIf .Value = "Credit" Then
Sheets("Sheet1").Range("A1:A1").Copy Destination:=Sheets("Sheet1").Range("A2:A2")
ElseIf .Value = "Savings" Then
Sheets("Sheet1").Range("A1:A1").Copy Destination:=Sheets("Sheet1").Range("A2:A2")
End If
End With
Next i
End With
A starting point would be great, as a lot of answers I find that are relatively similar are not similar enough for me to relate it to my project. I know that code might not be fixable in its current form. So far it works until "Sheets("Account Styles").Range("A1:G3")..."
Thanks in advance.
Obviously, there is still a lot of work in your project. In the code below I have streamlined your existing code a little so that you can see your next step more clearly. I hope it helps.
Sub AddNameNewSheet1()
' 21 May 2017
Dim WsStart As Worksheet
Dim WsNew As Worksheet
Dim AccName As String
Dim Rl As Long ' last row
Dim R As Long ' row counter
AccName = InputBox("Name for new account?")
If AccName = "" Then Exit Sub
Set WsNew = Worksheets.Add
With WsNew
.Name = AccName
.Cells(1, "D").Value = AccName
End With
Set WsStart = Worksheets("Start Page")
With WsStart
Rl = .Range("A" & Rows.Count).End(xlUp).Row
For R = 1 To Rl
Select Case .Cells(R, "A").value
Case "Debit"
.Range("A1:G3").Value = Sheets("Account Styles").Range("A1:G3").Value
Case "Credit", "Savings"
.Range("A2").Value = Sheets("Sheet1").Range("A1").Value
End Select
Next R
End With
End Sub

Insert entire row based upon prompted cell value

All, I have the following code, but I need to know how to amend it. I need a prompt or message box that asks me, which value in column A to look for. It should the find the corresponding value in Sheet1 Column A, and copy the Data from Column A to AL over to sheet2.
Here's my code:
Sub MM1()
Dim Check As Range, r As Long, lastrow2 As Long, lastrow As Long
Application.ScreenUpdating = False
lastrow = Worksheets("Sheet1").UsedRange.Rows.Count
lastrow2 = Worksheets("Sheet2").UsedRange.Rows.Count
If lastrow2 = 1 Then lastrow2 = 0
For r = lastrow To 2 Step -1
If Range("E" & r).Value = "Yes" Then
Rows(r).Cut Destination:=Worksheets("Sheet2").Range("A" & lastrow2 + 1)
lastrow2 = lastrow2 + 1
Else:
End If
Next r
Application.ScreenUpdating = True
End Sub
Also, this is to be a subset of code which will search for the exact row to insert at.
You don't need to do a manual loop through the rows in sheet1, just use VBA's native Find function. Also You're currently not getting user input, that can be achieved with an InputBox.
See the comments for details about the code.
This example copies the data from the first match:
Sub MM1()
Dim lastrowsheet2 As Long
' Use last cell in UsedRange for its row number,
' if row 1,2,... aren't used, then UsedRange will be shorter than you expect!
With ThisWorkbook.Sheets("Sheet2").UsedRange
lastrowsheet2 = .Cells(.Cells.Count).Row
End With
' Get user input for a search term
Dim userinput As String
userinput = InputBox("Enter a value to search for.", "Column A Search")
' Search for value
Dim findrange As Range
Set findrange = ThisWorkbook.Sheets("Sheet1").Columns("A").Find(what:=userinput, lookat:=xlWhole, LookIn:=xlValues)
If findrange Is Nothing Then
MsgBox "No matching search results"
Else
lastrowsheet2 = lastrowsheet2 + 1
' Copy values in found row to sheet 2, in new last row
ThisWorkbook.Sheets("Sheet2").Range("A" & lastrowsheet2, "AL" & lastrowsheet2).Value _
= ThisWorkbook.Sheets("Sheet1").Range("A" & findrange.Row, "AL" & findrange.Row).Value
End If
End Sub
This example copies the data from the every match in the column:
Sub MM1()
' Speed improvements
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' Use last cell in UsedRange for its row number,
' if row 1,2,... aren't used, then UsedRange will be shorter than you expect!
Dim lastrowsheet2 As Long
With ThisWorkbook.Sheets("Sheet2").UsedRange
lastrowsheet2 = .Cells(.Cells.Count).Row
' If sheet is completely empty, make sure data will be inserted on row 1 not 2
If lastrowsheet2 = 1 And .Cells(1).Value = "" Then lastrowsheet2 = 0
End With
' Get user input for a search term
Dim userinput As String
userinput = InputBox("Enter a value to search for.", "Column A Search")
' Search for value
Dim findrange As Range
Dim firstaddress As String
Set findrange = ThisWorkbook.Sheets("Sheet1").Columns("A").Find(what:=userinput, lookat:=xlWhole, LookIn:=xlValues)
If findrange Is Nothing Then
MsgBox "No matching search results"
Else
firstaddress = findrange.Address
Do
lastrowsheet2 = lastrowsheet2 + 1
' Copy values in found row to sheet 2, in new last row
ThisWorkbook.Sheets("Sheet2").Range("A" & lastrowsheet2, "AL" & lastrowsheet2).Value _
= ThisWorkbook.Sheets("Sheet1").Range("A" & findrange.Row, "AL" & findrange.Row).Value
' Find next match
Set findrange = ThisWorkbook.Sheets("Sheet1").Columns("A").FindNext(findrange)
' Loop until the Find has wrapped back around, or value not found any more
Loop While Not findrange Is Nothing And findrange.Address <> firstaddress
End If
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub

Troubleshooting Excel VBA Code

The point of this code is to take user inputs from a "Remove Flags" tab in which the user puts an item number and what program it belongs to, filters the "Master List" tab by the item number and the program, then match the name of the flag to the column and delete the flag. However the offset is not working. It is instead deleting the header. When I step through it everything works fine until the line I marked with '*******.
I am fairly new to VBA and am self taught so any and all help is greatly appreciated. Thank you very much for your time.
EDIT: Removed "On Error Resume Next" and fixed some spelling errors. Current issue is with rng not having >1 rows when it is filtered and definitely has two rows (one row is the header, one row is the returned data.)
Sub RemoveFlag()
Dim cel As Range
Dim rg As Range
Dim d As Double
Dim i As Integer
Dim m As Integer
Dim n As Integer
Dim rng As Range
Dim wsMaster As Worksheet
Dim wsFlag As Worksheet
Set wsMaster = Worksheets("Master List")
Set wsFlag = Worksheets("Remove Flags")
i = 6
'If there is no data. Do nothing.
If wsFlag.Range("C6") = "" Then
wsFlag.Activate
Else
Application.ScreenUpdating = False
'Add Leading zeroes
wsFlag.Activate
Set rg = Range("C6")
Set rg = Range(rg, rg.Worksheet.Cells(Rows.Count, rg.Column).End(xlUp))
rg.NumberFormat = "#"
For Each cel In rg.Cells
If IsNumeric(cel.Value) Then
d = Val(cel.Value)
cel.Value = Format(d, "000000000000000000") 'Eighteen digit number
End If
Next
'Clear all the filters on the Master List tab.
wsMaster.Activate
If wsMaster.AutoFilterMode = True Then
wsMaster.AutoFilterMode = False
End If
'Loop through all lines of data
Do While wsFlag.Cells(i, 3).Value <> ""
'Filter by the SKU number
wsMaster.Range("A1").AutoFilter Field:=4, Criteria1:=wsFlag.Cells(i, 3).Value
'Filter by the Program
wsMaster.Range("A1").AutoFilter Field:=2, Criteria1:=wsFlag.Cells(i, 2).Value
'If the filter is not empty find the column of the flag
Set rng = wsMaster.UsedRange.SpecialCells(xlCellTypeVisible)
If (rng.Rows.Count > 1) Then
wsMaster.Range("A1:Z1").Find(wsFlag.Cells(i, 4), LookIn:=xlValues).Activate
n = ActiveCell.Column
Sheets("Master List").Range.Offset(1, 0).SpecialCells(xlCellTypeVisible).Select
m = ActiveCell.Row
Cells(m, n) = ""
wsFlag.Activate
wsFlag.Range(Cells(i, 2), Cells(i, 4)).ClearContents
Else
wsFlag.Activate
wsFlag.Range(Cells(i, 2), Cells(i, 4)).Copy
wsFlag.Range("F4").End(xlDown).Offset(1, 0).Activate
ActiveCell.PasteSpecial Paste:=xlPasteValues
wsFlag.Range(Cells(i, 2), Cells(i, 4)).ClearContents
End If
wsMaster.Activate
wsMaster.AutoFilterMode = False
i = i + 1
Loop
'Make sure the entire Master List tab is not highlighted and pull the 'highlighted cell' to A1 in both tabs.
wsMaster.Activate
wsMaster.Range("A1").Activate
wsFlag.Activate
Range("A1").Activate
'Unfreeze the screen
Application.ScreenUpdating = True
End If
End Sub
As #Zerk suggested, first set two Worksheet variables at top of code:
Dim wsMaster As Worksheet
Dim wsRemoveFlags As Worksheet
Set wsMaster = Worksheets("Master List")
Set wsRemoveFlags = Worksheets("Remove Flags")
Then replace all other instances of Worksheets("Master List") with wsMaster and Worksheets("Remove Flags") with wsRemoveFlags.
Sometimes it's easier to just loop through your rows and columns. Something like the following:
Replace everything between:
Do While wsFlag.Cells(i, 3).Value <> ""
...
Loop
with:
Do While wsFlag.Cells(i, 3).Value <> ""
Dim r As Long ' Rows
Dim c As Long ' Columns
Dim lastRow As Long
Dim found As Boolean
lastRow = wsMaster.Cells.SpecialCells(xlLastCell).Row
found = False
For r = 2 To lastRow ' Skipping Header Row
' Find Matching Program/SKU
If wsMaster.Cells(r, 2).Value = wsFlag.Cells(i, 2).Value _
And wsMaster.Cells(r, 3) = wsFlag.Cells(i, 3).Value Then
' Find Flag in Row
For c = 1 To 26 ' Columns A to Z
If wsMaster.Cells(r, c) = wsFlag.Cells(i, 4) Then
' Found Flag
wsMaster.Cells(r, c) = ""
found = True
Exit For ' if flag can be in more than one column, remove this.
End If
Next 'c
End If
Next 'r
If Not found Then
' Here is where you need to put code if Flag wsFlag.Cells(i, 4) not found.
End If
Loop

Split a single workbook into multiple workbooks containing multiple worksheets using Excel VBA

I have a workbook with single worksheet as given below.
I want to split it into many workbooks containing many worksheets according to the values in it.
I want to make 'n' number of workbooks according to 'n' unique values of column 1 as in the picture. And I want to make 'm' worksheets according to 'm' unique values of column 2 as in the picture.
Each worksheet contains values as in the picture.
Actually I want to make a chart with 3 series. So I have to make data table as in the picture with columns 'levels', 'chart_vlaue_1', 'chart_vlaue_2', 'chart_vlaue_3' in each worksheet.
Also I want to generate charts in each of the worksheet.
Please help me a create a sample chart. I will work on it.
Please help me.
Try below, below should sort your data into the correct sheets/workbooks and create you a chart for each sheet. f_Path is the file path of where you will save these files. if the files already exist the code will SKIP THESE
Sub main()
Dim f_Path
f_Path = "C:\" 'Filepath to save files to
With ActiveSheet 'run on activesheet
If .Cells(2, 1).Value <> "" Then 'if A2 not blank
For Each cell In .Range("A2:" & .Range("A2").End(xlDown).Address)
If Dir(f_Path & cell.Value & ".xls") <> "" Then
'exists
If IsWorkBookOpen(f_Path & cell.Value & ".xls") Then
'open
Else
GoTo Skipper 'not open
End If
Workbooks(cell.Value & ".xls").Activate
On Error Resume Next
Sheets(cell.Offset(0, 1).Value).Select
If Err.Number <> 0 Then
Worksheets.Add().Name = cell.Offset(0, 1).Value
End If
On Error GoTo 0
lastrow = ActiveSheet.Range("A1").End(xlDown).Row - 1
If lastrow = 1048575 Then 'First time
With ActiveSheet
.Range("A1").Value = "Levels"
.Range("B1").Value = "Chart_Value1"
.Range("C1").Value = "Chart_Value2"
.Range("D1").Value = "Chart_Value3"
.Range("A2").Value = cell.Offset(0, 2).Value
.Range("B2").Value = cell.Offset(0, 3).Value
.Range("C2").Value = cell.Offset(0, 5).Value
.Range("D2").Value = cell.Offset(0, 7).Value
End With
Else
With ActiveSheet
.Range("A2").Offset(0 + lastrow, 0).Value = cell.Offset(0, 2).Value
.Range("B2").Offset(0 + lastrow, 0).Value = cell.Offset(0, 3).Value
.Range("C2").Offset(0 + lastrow, 0).Value = cell.Offset(0, 5).Value
.Range("D2").Offset(0 + lastrow, 0).Value = cell.Offset(0, 7).Value
End With
End If
ActiveWorkbook.Save
Else
'does not
Set wb = Workbooks.Add(xlWBATWorksheet)
With ActiveSheet
.Name = cell.Offset(0, 1).Value
.Range("A1").Value = "Levels"
.Range("B1").Value = "Chart_Value1"
.Range("C1").Value = "Chart_Value2"
.Range("D1").Value = "Chart_Value3"
.Range("A2").Value = cell.Offset(0, 2).Value
.Range("B2").Value = cell.Offset(0, 3).Value
.Range("C2").Value = cell.Offset(0, 5).Value
.Range("D2").Value = cell.Offset(0, 7).Value
End With
ActiveWorkbook.SaveAs f_Path & cell.Value & ".xls", 56
End If
Skipper:
Next
End If
End With
For Each wb In Workbooks
If ThisWorkbook.Name <> wb.Name Then
For Each ws In wb.Worksheets
With ws
Set Rng = ws.UsedRange
ws.Shapes.AddChart
End With
Next
wb.Close True
End If
Next
End Sub
Function IsWorkBookOpen(FileName As String)
Dim ff As Long, ErrNo As Long
On Error Resume Next
ff = FreeFile()
Open FileName For Input Lock Read As #ff
Close ff
ErrNo = Err
On Error GoTo 0
Select Case ErrNo
Case 0: IsWorkBookOpen = False
Case 70: IsWorkBookOpen = True
Case Else: Error ErrNo
End Select
End Function
The following code will parse the data in first two columns create workbooks for each unique cell value from first column and sheet for each unique cell value from second column. It finally adds charts of type xlColumnClustered and saves and closes all the new books. Source data can be un-sorted.
Important: change the constants TargetPath and/or DataBookName, DataSheetName according to your conditions.
Option Explicit
' ---------------------------------------------------------------------------------------
' Results will be saved 'TargetPath' path. This path must be changed according to your PC
' Change this path:
Private Const TargetPath As String = "C:\Temp\Abdul_Shiyas\Results\"
' ---------------------------------------------------------------------------------------
' ---------------------------------------------------------------------------------------
' Expected data are contain in sheet named "Data" in wokbook with the name "Data.xlsx"
' This names can be changed according to your wokbook with data.
Private Const DataBookName As String = "Data.xlsx"
Private Const DataSheetName As String = "Data"
' ---------------------------------------------------------------------------------------
Private sourceBook As Workbook
Private sht As Worksheet
Private book As Workbook
Private books As Collection
Private header As Range
Private data As Range
Private criteria As Range
Private criteriaRow As Range
Private bookName As String
Private sheetName As String
Private newChart As Shape
Public Sub ParseToWorkbooks()
' Important:
' Data are expected to begin in cell "A1" and should not contain any blank rows or blank columns
Set sourceBook = Workbooks(DataBookName)
Set data = sourceBook.Worksheets(DataSheetName).Range("A1").CurrentRegion
Set header = data.Rows(1)
Set data = data.Offset(1, 0).Resize(data.Rows.Count - 1, data.Columns.Count)
Set criteria = data.Resize(data.Rows.Count, 2)
Set header = header.Offset(0, criteria.Columns.Count).Resize(1, header.Columns.Count - criteria.Columns.Count)
Set books = New Collection
For Each criteriaRow In criteria.Rows
bookName = Trim(criteriaRow.Cells(1))
sheetName = Trim(criteriaRow.Cells(2))
' get the book first
Set book = Nothing
On Error Resume Next
Set book = books(bookName)
On Error GoTo 0
If book Is Nothing Then
Set book = Workbooks.Add
Application.DisplayAlerts = False
book.SaveAs Filename:=TargetPath & bookName
Application.DisplayAlerts = True
books.Add book, bookName
End If
' get the sheet then
Set sht = Nothing
On Error Resume Next
Set sht = book.Worksheets(sheetName)
On Error GoTo 0
If sht Is Nothing Then
Set sht = book.Worksheets.Add
sht.Name = sheetName
header.Copy Destination:=sht.Range("A1")
End If
' paste data to the sheet
criteriaRow.Cells(2).Offset(0, 1).Resize(1, data.Columns.Count - criteria.Columns.Count).Copy _
Destination:=sht.Cells(sht.Rows.Count, 1).End(xlUp).Offset(1, 0)
Next criteriaRow
' finally and chart, save and close each new book
For Each book In books
For Each sht In book.Worksheets
If sht.Range("A1").Value <> "" Then
Set newChart = sht.Shapes.AddChart
newChart.Chart.SetSourceData Source:=sht.Range("A1").CurrentRegion
newChart.Chart.ChartType = xlColumnClustered
End If
Next sht
book.Close True
Next book
End Sub