Extracting and copying data in an excel file - vba

I'm extracting data froman excel file that is inside the parameter of the dates provided. But this code is not working. Anybody can help me figure this out?
Set src = wb.Sheets("Request Log Extract")
Set dest = ThisWorkbook.Sheets("Resolution Time Performance")
srcRow = src.Cells(src.Rows.Count, "K").End(xlUp).Row
destRow = dest.Cells(dest.Rows.Count, "E").End(xlUp).Row + 1
wb.Activate
For i = 2 To srcRow
If src.Cells("K" & i) >= txtStartDate.Value Or src.Cells("K" & i) <= .txtEndDate.Value Then
src.Cells("K" & i).Copy
dest.Activate
dest.Cells("E" & i).Paste
src.Activate
End If
Next
This returns an error saying :
Invalid procedure call or argument.
NOTE
txtStartDate and txtEndDate are date Types.
If I use OR in the If condition, all data were copied, but if I used And, no data is copied. I don't know whats going on.
VALUES
txtStartDate 05/13/2016
txtEndDate 05/18/2016
k2 05/14/2016

Im not sure with your txtStartDate and txtEndDate variables, but look at my code
I declared your variables, but please specify date types, also i removed dot from txtEndDate and changed cell references and now it works.
Sub extractData()
Dim src
Dim dest
Dim wb As Workbook
Set wb = ThisWorkbook
Dim txtStartDate
Dim txtEndDate
Set src = wb.Sheets("Request Log Extract")
Set dest = ThisWorkbook.Sheets("Resolution Time Performance")
srcRow = src.Cells(src.Rows.Count, "K").End(xlUp).Row
destRow = dest.Cells(dest.Rows.Count, "E").End(xlUp).Row + 1
txtStartDate = 0
txtEndDate = 100
For i = 2 To srcRow
If src.Cells(i, "K").Value > txtStartDate Or src.Cells(i, "K").Value < txtEndDate Then
src.Cells(i, "K").Copy
dest.Activate
dest.Cells(i, "E").PasteSpecial
src.Activate
End If
Next
End Sub

I think it's a date value issue
Moreover I'm guessing your code is within some userform pane and activated at some button click after which it has to compare two textboxes values to some cells content and copy/paste values accordingly
should my guessing be right (finger crossed...) try this:
Option Explicit
Private Sub CommandButton1_Click()
Dim src As Worksheet, dest As Worksheet
Dim srcRow As Long, destRow As Long, i As Long
Dim startDate As Date, endDate As Date, cellDate As Date
With Me
If Not ValidateDate("txtStartDate", .txtStartDate.Value, startDate) Then Exit Sub
If Not ValidateDate("txtEndDate", .txtEndDate.Value, endDate) Then Exit Sub
Set src = ActiveWorkbook.Sheets("Request Log Extract") '<~~ change workbook reference as per your need
Set dest = ThisWorkbook.Sheets("Resolution Time Performance")
srcRow = src.Cells(src.Rows.Count, "K").End(xlUp).Row
destRow = dest.Cells(dest.Rows.Count, "E").End(xlUp).Row + 1
For i = 2 To srcRow
If ValidateDate("src.Range(""K" & i & """)", src.Range("K" & i), cellDate) Then
If cellDate >= startDate And cellDate <= endDate Then src.Range("K" & i).Copy dest.Range("E" & i)
End If
Next
End With
End Sub
Function ValidateDate(textName As String, textValue As String, retDate As Date) As Boolean
ValidateDate = IsDate(textValue)
If ValidateDate Then
retDate = DateValue(textValue)
Else
MsgBox textValue & " is not a valid date" & vbCrLf & "please input a new value for " & textName
End If
End Function
should my guessing be wrong, still the code above can give you some suggestions as to the date value issue

This code is working for me:
Sub Demo()
Dim wb As Workbook
Dim txtStartDate As Date, txtEndDate As Date
Set wb = ActiveWorkbook
Set src = wb.Sheets("Request Log Extract")
Set dest = wb.Sheets("Resolution Time Performance")
srcRow = src.Cells(src.Rows.Count, "K").End(xlUp).Row
destRow = dest.Cells(dest.Rows.Count, "E").End(xlUp).Row + 1
txtStartDate = "05/13/2016"
txtEndDate = "05/18/2016"
For i = 2 To srcRow
If src.Range("K" & i).Value >= txtStartDate And src.Range("K" & i).Value <= txtEndDate Then
src.Range("K" & i).Copy Destination:=dest.Range("E" & i)
End If
Next
End Sub

Related

Split data into multiple workbooks based on cell value in Excel using vba

Each month I get our sales report and it contains quantities of goods we sold along with product details, and I created a template using vba where user can specify a product and it can create a excel report for them.
However, I would like to expand/modify so if I have multiple excel reports instead of just one report. I would like excel to separate however many product codes I input or listed.
Now, I added a tab called list in my template which I can list the # of product codes (the 4 digit number, in column A) where vba should read from but I need help on modifying the codes so instead of asking the user, it reads the list instead. Secondly, since master file contains all of the products and I maybe just need 20 or 30 of them, I will need the vba codes to be flexible as possible.
The way i set it up, I am basically updating/copying new info from Master file into Monthly Template and re-saving Monthly Template as product codes product as of 9.1.2017 file.
Sub monthly()
Dim x1 As Workbook, y1 As Workbook
Dim ws1, ws2 As Worksheet
Dim LR3, LR5 As Long
Dim ws3 As Worksheet
Dim Rng3, Rng4 As Range
Dim x3 As Long
Set x1 = Workbooks("Master.xlsx")
Set y1 = Workbooks("Monthly Template.xlsm")
Set ws1 = x1.Sheets("Products")
Set ws2 = y1.Sheets("Products")
Set ws3 = y1.Sheets("List")
ws2.Range("A3:AA30000").ClearContents
ws1.Cells.Copy ws2.Cells
x1.Close True
LR5 = ws3.Cells(Rows.Count, "A").End(xlUp).Row
With y1.Sheets("List")
Range("A1:A32").Sort key1:=Range("A1"), Order1:=xlAscending
End With
LR3 = ws2.Cells(Rows.Count, "A").End(xlUp).Row
Set Rng3 = ws2.Range("AC3:AC" & LR3)
Set Rng4 = ws3.Range("A1:A" & LR5)
For n = 3 To LR3
ws2.Cells(n, 29).FormulaR1C1 = "=LEFT(RC[-21], 4)"
Next n
With y1.Sheets("List")
j = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
With ws2
l = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
For i = 1 To j
For k = 3 To l
If Sheets("List").Cells(i, 1).Value = Sheets("Products").Cells(k, 29).Value Then
With Sheets("Output")
m = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
Sheets("Output").Rows(m + 1).Value = Sheets("Products").Rows(k).Value
End If
Next k
Next i
Sheets("Output").Columns("AC").ClearContents
Dim cell As Range
Dim dict As Object, vKey As Variant
Dim Key As String
Dim SheetsInNewWorkbook As Long
Dim DateOf As Date
DateOf = DateSerial(Year(Date), Month(Date), 1)
With Application
.ScreenUpdating = False
SheetsInNewWorkbook = .SheetsInNewWorkbook
.SheetsInNewWorkbook = 1
End With
Set dict = CreateObject("Scripting.Dictionary")
With ThisWorkbook.Worksheets("List")
For Each cell In .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
Key = Left(cell.Value, 4)
'Store an ArrayList in the Scripting.Dictionary that can be retrieved using the Product Key
If Not dict.exists(Key) Then dict.Add Key, CreateObject("System.Collections.ArrayList")
Next
End With
With Workbooks("Monthly Template.xlsm").Worksheets("Output")
For Each cell In .Range("H2", .Range("A" & .Rows.Count).End(xlUp))
Key = Left(cell.Value, 4)
'Add the Products to the ArrayList in the Scripting.Dictionary that is associated with the Product Key
If dict.exists(Key) Then dict(Key).Add cell.Value
Next
End With
For Each vKey In dict
If dict(vKey).Count > 0 Then
With Workbooks.Add
With .Worksheets(1)
.Name = "Products"
' .Range("A1").Value = "Products"
Workbooks("Monthly Template.xlsm").Worksheets("Output").Cells.Copy Worksheets(1).Cells
For Z = 1 To LR5
For x3 = Rng3.Rows.Count To 1 Step -1
If InStr(1, Rng3.Cells(x3, 1).Text, Workbooks("Monthly Template.xlsm").Worksheets("List").Cells(Z, 1).Text) = 0 Then
Rng3.Cells(x3, 1).EntireRow.Delete
End If
Next x3
Next Z
'.Range("A2").Resize(dict(vKey).Count).Value = Application.Transpose(dict(vKey).ToArray)
End With
.SaveAs Filename:=getMonthlyFileName(DateOf, CStr(vKey)), FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
.Close SaveChanges:=False
End With
End If
Next
With Application
.ScreenUpdating = True
.SheetsInNewWorkbook = SheetsInNewWorkbook
End With
End Sub
Function getMonthlyFileName(DateOf As Date, Product As String) As String
Dim path As String
path = ThisWorkbook.path & "\Product Reports\"
If Len(Dir(path, vbDirectory)) = 0 Then MkDir path
path = path & Format(DateOf, "yyyy") & "\"
If Len(Dir(path, vbDirectory)) = 0 Then MkDir path
path = path & Format(DateOf, "mmm") & "\"
If Len(Dir(path, vbDirectory)) = 0 Then MkDir path
getMonthlyFileName = path & "Product - " & Product & Format(DateOf, " mmm.dd.yyyy") & ".xlsx"
End Function
I seen no reason why to save copies of Monthly Template.xlsm. The OP's code simply creates a list on a worksheet and saves it to file. I might be some formatting missing that would normally get saved over from the Master File.
getMonthlyFileName(DateOf, Product) - creates a file path (Root Path\Year of Date\Month of Date\Product - Prodcut mmm.dd.yyyy.xlsx. In this way, the Product files can be stored in an easy to lookup structure.
Sub CreateMonthlyReports()
Dim cell As Range
Dim dict As Object, vKey As Variant
Dim Key As String
Dim SheetsInNewWorkbook As Long
Dim DateOf As Date
DateOf = DateSerial(Year(Date), Month(Date), 1)
With Application
.ScreenUpdating = False
SheetsInNewWorkbook = .SheetsInNewWorkbook
.SheetsInNewWorkbook = 1
End With
Set dict = CreateObject("Scripting.Dictionary")
With ThisWorkbook.Worksheets("List")
For Each cell In .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
Key = Left(cell.Value, 4)
'Store an ArrayList in the Scripting.Dictionary that can be retrieved using the Product Key
If Not dict.exists(Key) Then dict.Add Key, CreateObject("System.Collections.ArrayList")
Next
End With
With Workbooks("Master.xlsx").Worksheets("Products")
For Each cell In .Range("H2", .Range("H" & .Rows.Count).End(xlUp))
Key = Left(cell.Value, 4)
'Add the Products to the ArrayList in the Scripting.Dictionary that is associated with the Product Key
If dict.exists(Key) Then dict(Key).Add cell.Value
Next
End With
For Each vKey In dict
If dict(vKey).Count > 0 Then
With Workbooks.Add
With .Worksheets(1)
.Name = "Products"
.Range("A1").Value = "Products"
.Range("A2").Resize(dict(vKey).Count).Value = Application.Transpose(dict(vKey).ToArray)
End With
.SaveAs FileName:=getMonthlyFileName(DateOf, CStr(vKey)), FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
.Close SaveChanges:=False
End With
End If
Next
With Application
.ScreenUpdating = True
.SheetsInNewWorkbook = SheetsInNewWorkbook
End With
End Sub
Function getMonthlyFileName(DateOf As Date, Product As String) As String
Dim path As String
path = ThisWorkbook.path & "\Product Reports\"
If Len(Dir(path, vbDirectory)) = 0 Then MkDir path
path = path & Format(DateOf, "yyyy") & "\"
If Len(Dir(path, vbDirectory)) = 0 Then MkDir path
path = path & Format(DateOf, "mmm") & "\"
If Len(Dir(path, vbDirectory)) = 0 Then MkDir path
getMonthlyFileName = path & "Product - " & Product & Format(DateOf, " mmm.dd.yyyy") & ".xlsx"
End Function
Try two loops for this, making sure you sort by the product in the main list to make this a little quicker.
Dim i as Long, j as Long, k as Long, l as Long, m as Long
With Sheets("List")
j = .Cells( .Rows.Count, 1).End(xlUp).Row
End With
With Sheets("Products")
l = .Cells( .Rows.Count, 1).End(xlUp).Row
End With
For i = 2 to j
For k = 2 to l
If Sheets("List").Cells(i,1).Value = Sheets("Products").Cells(k,1).Value Then
With Sheets("Output")
m = .Cells( .Rows.Count, 1).End(xlUp).Row
End With
Sheets("Output").Rows(m+1).Value = Sheets("Products").Rows(k).Value
End If
Next k
Next i
Edit
Will try to piecemeal something to give at least a lead to splitting into different sheets, rather than having one output sheet (this will not be tested, just free-coding):
Dim i as Long, j as Long, k as Long, l as Long, m as Long, n as String
With Sheets("List")
j = .Cells( .Rows.Count, 1).End(xlUp).Row
End With
With Sheets("Products")
l = .Cells( .Rows.Count, 1).End(xlUp).Row
End With
For i = 2 to j
n = Sheets("List").Cells(i,1).Value
Sheets.Add(After:=Sheets(Sheets.Count)).Name = n
Sheets(n).Cells(1,1).Value = n
Sheets(n).Rows(2).Value = Sheets("Products").Rows(1).Value
For k = 2 to l
With Sheets(n)
If .Cells(1,1).Value = Sheets("Products").Cells(k,1).Value Then
m = .Cells( .Rows.Count, 1).End(xlUp).Row
.Rows(m+1).Value = Sheets("Products").Rows(k).Value
End If
Next k
Next i
I don't know why some people doing VBA thinks declaring all the variables with weird names before a thousand lines of code is a good idea.........
Anyways..back to the question, I believe what you are trying to achieve is:
1) Specify a list whilst the code iterates through the list and filters the data based on the listed items.
2) Creates a workbook where the filtered the data is copied over.
3) saving the workbook to somewhere you'll specify, with a specific name.
So naturally, your programme access point should be the one that iterates through the specified list, which should be your main function.
Then inside main function you'll have a Sub that deals with whatever the product ID is, and then filters on your product ID, then copies the data into a newly created workbook.
Last step would be naming the new workbook and saving it close it.
So here is some code skeleton that hopefully will help you with creating the monthly reports. You'll have to write yourself how you want to copy the data from your master workbook to the destination workbook (it should be simple enough, just filter the source list and copy the results to the destination workbook, no dictionary nor arraylist is needed).
Sub main()
Dim rngIdx As Range
Set rngIdx = ThisWorkbook.Sheets("where your list is").Range("A1")
With Application
.DisplayAlerts = False
.ScreenUpdating = False
End With
While (rngIdx.Value <> "")
Call create_report(rngIdx.Value)
Set rngIdx = rngIdx.Offset(1, 0)
Wend
With Application
.DisplayAlerts = True
.ScreenUpdating = True
End With
End Sub
Sub create_report(ByVal product_ID As String)
Dim dest_wbk As Workbook
Set dest_wbk = Workbooks.Add
Call do_whatever(ThisWorkbook, dest_wbk, product_ID)
dest_wbk.SaveAs getMonthlyFileName(some_date, product_ID)
dest_wbk.Close
End Sub
Sub do_whatever(source_wbk As Workbook, dest_wbk As Workbook, ByVal product_ID As String)
' this is the code where you copy from your master data to the destination workbook
' modify sheet names, formatting.......etc.
End Sub

Convert headers and row level data to column level

I have very little experience working with VBA, so I'm having a hard time looking up what I am trying to do because I am having a hard time putting what I am trying to do into words.
I have been struggling to write a code to do the below task for the past few days.
Basically what I am trying to do is to convert a set of data to different format.
This what my source data looks like.
Data:
and I need it to look like this
FinalLook:
I've a already setup a code which is lengthy and incomplete.
FIRST PART
I started with retrieving a part of a data (AQ:BA) and then convert to the format in sheet2 with the below code.
Sub FirstPart()
Dim lastRow As Long
Dim Laaastrow As Long
Sheets("sheet2").Range("a2:A5000").ClearContents
lastRow = Sheets("Sheet1").Range("c" & Rows.Count).End(xlUp).Row
Sheets("Sheet2").Range("A2:A" & lastRow).Value = Sheets("Sheet1").Range("c5:c" & lastRow).Value
Sheets("Sheet2").Range("b2:l" & lastRow).Value = Sheets("Sheet1").Range("aq5:ba" & lastRow).Value
End Sub
But.. the problem i am facing with this code is that it pulls all the data, i do not want it to pull all the values, but only the ones which is not empty or 0. In other words, if AQ6:BA6 is empty, script should skip this particular row and go the next one.
SECOND PART (converting the sheet2 data to the final format)
Sub NormalizeSheet()
Dim wsSheet2 As Worksheet
Dim wsSheet4 As Worksheet
Dim strKey As String
Dim clnHeader As Collection
Dim lngColumnCounter As Long
Dim lngRowCounterSheet2 As Long
Dim lngRowCounterSheet4 As Long
Dim rngCurrent As Range
Dim varColumn As Variant
Set wsSheet2 = ThisWorkbook.Worksheets("Sheet2")
Set wsSheet4 = ThisWorkbook.Worksheets("Sheet4")
Set clnHeader = New Collection
wsSheet4.Range("c2:c5000").ClearContents
wsSheet4.Range("e2:e5000").ClearContents
wsSheet4.Range("g2:g5000").ClearContents
lngColumnCounter = 2
lngRowCounterSheet2 = 1
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
Do Until IsEmpty(rngCurrent.Value)
clnHeader.Add rngCurrent.Value, CStr(lngColumnCounter)
lngColumnCounter = lngColumnCounter + 1
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
Loop
lngRowCounterSheet2 = 2
lngRowCounterSheet4 = 1
lngColumnCounter = 1
Do While Not IsEmpty(wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter))
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
strKey = rngCurrent.Value
lngColumnCounter = 2
Do While Not IsEmpty(wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter))
Set rngCurrent = wsSheet2.Cells(lngRowCounterSheet2, lngColumnCounter)
If rngCurrent.Value = "NULL" Then
Else
wsSheet4.Range("c" & lngRowCounterSheet4).Offset(1, 0).Value = strKey
wsSheet4.Range("e" & lngRowCounterSheet4).Offset(1, 0).Value = clnHeader(CStr(lngColumnCounter))
wsSheet4.Range("g" & lngRowCounterSheet4).Offset(1, 0).Value = rngCurrent.Value
lngRowCounterSheet4 = lngRowCounterSheet4 + 1
End If
lngColumnCounter = lngColumnCounter + 1
Loop
lngRowCounterSheet2 = lngRowCounterSheet2 + 1
lngColumnCounter = 1
Loop
End Sub
I got this code from another thread posted here on stakcoverflow, i modified a bit to get this work.
The problem i am encountering here is that if Sheet2 B2 is empty, the codes doesnt check sheet C2 instead it skips the whole row, which is not right here.
I know this sounds complicated, and this approach of mine may not be even feasible.
Is there ANY OTHER WAY to do this? Is there any other way to get this in a single shot instead of breaking down the data and move each set of columns to sheet2 then to final format?
See how you get on with this. You'll have to adjust range references, and possibly sheet names
Sub x()
Dim r As Long, c As Range
With Sheet1
For r = 5 To .Range("A" & Rows.Count).End(xlUp).Row
For Each c In .Range(.Cells(r, "AQ"), .Cells(r, "BK")).SpecialCells(xlCellTypeConstants)
If c.Value > 0 Then
Sheet2.Range("A" & Rows.Count).End(xlUp)(2).Value = .Range("B1").Value
Sheet2.Range("B" & Rows.Count).End(xlUp)(2).Value = .Cells(r, 1).Value
Sheet2.Range("C" & Rows.Count).End(xlUp)(2).Value = .Cells(r, 2).Value
Sheet2.Range("D" & Rows.Count).End(xlUp)(2).Value = .Cells(3, c.Column).Value
Sheet2.Range("E" & Rows.Count).End(xlUp)(2).Value = .Cells(4, c.Column).Value
Sheet2.Range("F" & Rows.Count).End(xlUp)(2).Value = "(blank)"
Sheet2.Range("G" & Rows.Count).End(xlUp)(2).Value = c.Value
End If
Next c
Next r
End With
Sheet2.Range("A1").Resize(, 7) = Array("TOPHEADER", "HEADER1", "HEADER2", "FROM", "TO", "TYPE", "UNIT")
End Sub

VBA Countifs error

I have a bit of code I've written and I'm having trouble with a certain line (Countifs statement). I haven't ever used this in VBA before so I think it might be something to do with Syntax? Please could someone take a look and let me know?
Thanks very much!
Sub TradeCopy()
'Declare Variables
Dim x As Worksheet
Dim y As Worksheet
Dim z As Range
Dim FirstRow As Integer
Dim LastRow As Long
Dim i As Long
Dim j As Long
Dim s As String
Dim t As String
Dim count As Long
Dim startdate As Long
On Error GoTo ERROREND
Application.DisplayAlerts = False
Application.EnableEvents = False
'Setting Values
s = ActiveWorkbook.Sheets("Name Creator").Range("B4")
Set x = ActiveWorkbook.Sheets(s)
t = ActiveWorkbook.Sheets("Name Creator").Range("B5")
Set y = ActiveWorkbook.Sheets(t)
startdate = ActiveWorkbook.Sheets("Name Creator").Range("B3")
'Find Cell where name occurs
Set z = x.Columns("A").Find(what:="trade id", LookIn:=xlValues, Lookat:=xlWhole)
'Return Start Row number
FirstRow = z.Row + 1
'Return Last Row number
LastRow = x.Range("A" & Rows.count).End(xlUp).Row
'Clear Existing Range of Values
y.Rows(2 & ":" & Rows.count).ClearContents
Below is the code giving problems, specifically the "count = " line when running debugger.
'Loop to highlight cells based on conditions
For i = FirstRow To LastRow
count = Application.WorksheetFunction.CountIfs(x.Range("B:B"), x.Range(i, 2), x.Range("L:L"), "<" & startdate)
Rest of code:
If (x.Cells(i, 21) = "Fra" Or x.Cells(i, 21) = "Swap" Or x.Cells(i, 21) = "Swaption" Or x.Cells(i, 21) = "BondOption" Or x.Cells(i, 21) = "CapFloor") And DateValue(x.Cells(i, 12).Value) > startdate And count <= 0 Then
x.Rows.Range("A" & i).Value.Interior.Color = vbRed
End If
Next i
'Loop to check for all 0 Cells and paste values
For j = FirstRow To LastRow
If x.Cells(j, 1).Interior.Color = vbRed Then
x.Rows.Range("A" & j).Value = y.Rows.Range("A" & j).Value
End If
Next j
'Remove Duplicates
y.Columns(2).RemoveDuplicates Columns:=Array(1)
Application.DisplayAlerts = True
Application.EnableEvents = True
MsgBox ("All Done!")
Exit Sub
ERROREND:
MsgBox ("Unexpected Error - Please Seek Assistance or Debug Code")
End Sub
I think you need to change .Range to .Cells in below:
count = Application.WorksheetFunction.CountIfs(x.Range("B:B"), x.Range(i, 2), x.Range("L:L"), "<" & startdate)
To:
count = Application.WorksheetFunction.CountIfs(x.Range("B:B"), x.Cells(i, 2), x.Range("L:L"), "<" & startdate)

Need to use code to get the last column in my data rather than use the column letter

My code currently uses the last column (in this case column o) searches all the rows in that column and clears the whole row which have a certain value in column o of that row. Please can I get some help to modify my code to automatically choose the last column rather than use the letter "o" or the value "15" of that column as for other spreadsheets it may not always use column o. See my working code below:
Sub edit_wb_1()
Dim wb As Workbook
Dim ws As Worksheet
Dim lastRow As Long, i As Long
Dim value As String
Dim OldDate, NewDate As String
OldDate = Format(DateSerial(Year(Date), Month(Date) - 1, 0), "ddmmyy")
NewDate = Format(DateSerial(Year(Date), Month(Date), 0), "ddmmyy")
Set wb = Workbooks.Open("C:\Users\ashah\Downloads\HistoricSummary.xls", 0)
Set ws = wb.Sheets("Historic Summary Page 1")
lastRow = ws.Range("o" & ws.Rows.Count).End(xlUp).Row
For i = lastRow To 2 Step -1
value = ws.Cells(i, 15).value ' Column O value.
' Check if it contains one of the keywords.
If (value Like "-") Then
ws.Rows(i).ClearContents
End If
Next
wb.SaveAs Filename:="C:\Users\ashah\Documents\TPS Shapes\TMB " & NewDate, FileFormat:=xlOpenXMLWorkbook
wb.Close
End Sub
Sub edit_wb_1()
Dim wb As Workbook
Dim ws As Worksheet
Dim lastRow As Long, i As Long
Dim lastColumn as Long
Dim value As String
Dim OldDate, NewDate As String
OldDate = Format(DateSerial(Year(Date), Month(Date) - 1, 0), "ddmmyy")
NewDate = Format(DateSerial(Year(Date), Month(Date), 0), "ddmmyy")
Set wb = Workbooks.Open("C:\Users\ashah\Downloads\HistoricSummary.xls", 0)
Set ws = wb.Sheets("Historic Summary Page 1")
lastRow = ws.Range("o" & ws.Rows.Count).End(xlUp).Row
lastColumn = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column ' gets last column in the first row (where you usually have headers so should be populated...
For i = lastRow To 2 Step -1
value = ws.Cells(i, lastColumn).value ' last col instead of Column O value.
' Check if it contains one of the keywords.
If (value Like "-") Then
ws.Rows(i).ClearContents
End If
Next
wb.SaveAs Filename:="C:\Users\ashah\Documents\TPS Shapes\TMB " & NewDate, FileFormat:=xlOpenXMLWorkbook
wb.Close
End Sub
The below alterations to your code should work.
I have made an assumption the row 1 is a header row.
I have also changed the variable name value to StrValue as value is used by built in Excel VBA functions and could cause ambiguity.
Sub edit_wb_1()
Dim wb As Workbook
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim Strvalue As String
Dim OldDate As String
Dim NewDate As String
OldDate = Format(DateSerial(Year(Date), Month(Date) - 1, 0), "ddmmyy")
NewDate = Format(DateSerial(Year(Date), Month(Date), 0), "ddmmyy")
Set wb = Workbooks.Open("C:\Users\ashah\Downloads\HistoricSummary.xls", 0)
Set ws = wb.Sheets("Historic Summary Page 1")
'This assumes row one is a header row
i = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
lastRow = ws.Cells(ws.Rows.Count, i).End(xlUp).Row
For i = lastRow To 2 Step -1
Strvalue = ws.Cells(i, 15).value ' Column O value.
' Check if it contains one of the keywords.
If (Strvalue Like "-") Then
ws.Rows(i).ClearContents
End If
Next
Set ws = Nothing
wb.SaveAs Filename:="C:\Users\ashah\Documents\TPS Shapes\TMB " & NewDate, FileFormat:=xlOpenXMLWorkbook
wb.Close 0
Set wb = Nothing
End Sub

Lookup dates and calculate expiratrion

I have two data reports where I sort the data in data report 1 and move it to a sheet called "List". To finish off the report I then,
Get a date from data report two for every line I have in the sorted list. To do this I have tried to take the action title in column "G" in the sheet "List" and then I search for it in the sheet "Data2" in column "C", then I return the row number and want to save a number there is in the column "G". This number is the days to deadline and can either be a positive or negative number.
Take today's date + / - the number and put the modified date and the sheet "Lists" in column "N" to be able to see when every task has deadline.
I can't get other kinds of data in the reports so I have to solve this with some VBA. The code I have tried is this.
Sub InsertDate()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim i As Integer
Dim RowNr As Long
Dim ActionTitle As String
Dim DaysToExp As Long
Dim ExpDate As Date
Dim Found As Range
Dim FoundRow As Long
Dim Sign As String
Dim Days As String
Dim RowNr2 As Long
ScreenUpdate = False
RowNr = ThisWorkbook.Worksheets("List").Range("A" & Rows.count).End(xlUp).row
RowNr2 = ThisWorkbook.Worksheets("Data2").Range("A" & Rows.count).End(xlUp).row
Set ws1 = ThisWorkbook.Worksheets("List")
Set ws2 = ThisWorkbook.Worksheets("Data2")
ws1.Range("N1").Value = "Expected start date"
For i = 2 To RowNr
ActionTitle = ws1.Range("G" & i).Value
Set Found = ws2.Range("C1:C" & RowNr2).Find(What:=ActionTitle, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows).Activate
FoundRow = ActiveCell.row
Days = ws2.Range("G" & FoundRow).Value
If Days = "" Then
DaysToExp = DaysToExp + 0
ElseIf Left(Days, 1) = "-" Then
Sign = "-"
DaysToExp = Replace(Days, "-", "")
Else
Sign = "+"
DaysToExp = DaysToExp + Days
End If
ExpDate = "=TODAY() & Sign & DaysToExp"
ThisWorkbook.Worksheets("List").Range("N" & i).Value = ExpDate
Next i
ScreenUpdate = True
End Sub
I've tightened up your code a bit and removed the .Find in place of a worksheet function .Match. You don't need to parse out the sign of Days since you can add a negative number to the date.
Sub InsertDate()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim i As Long
Dim RowNr As Long, DaysToExp As Long, FoundRow As Long, RowNr2 As Long
Dim ActionTitle As String, Sign As String, Days As String
Dim ExpDate As Date
Dim Found As Range
Application.ScreenUpdating = False
Set ws1 = ThisWorkbook.Worksheets("List")
Set ws2 = ThisWorkbook.Worksheets("Data2")
RowNr2 = ws2.Range("A" & Rows.Count).End(xlUp).Row
With ws1
RowNr = .Range("A" & Rows.Count).End(xlUp).Row
.Range("N1").Value = "Expected start date"
For i = 2 To RowNr
ActionTitle = ws1.Range("G" & i).Value
If CBool(Application.CountIf(ws2.Range("C1:C" & RowNr2), ActionTitle)) Then
FoundRow = Application.Match(ActionTitle, ws2.Range("C1:C" & RowNr2), 0)
Days = ws2.Range("G" & FoundRow).Value
ExpDate = Date + Days
.Range("N" & i).Value = ExpDate
Else
Debug.Print "missing " & ActionTitle
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
I threw a debug.print in that will report to the VBE's Immediate window if ActionTitle cannot be found.