Compare two cells, if equal then delete and replace - vba

I send data from one workbook to another. My macro copies and pastes the data into a masterdata document that stores all my data. After pasting the macro goes back and sets all my values to 0 before save then closing.
sub send()
Workbooks.Open "C:\Users\BB"
Worksheets("CC").Activate
Workbooks("AA").Activate
Worksheets("AA").Range("A3:F19").Copy
Workbooks("BB").Activate
ActiveSheet.Paste Destination:=Worksheets("CC").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
ActiveWorkbook.Save
ActiveWorkbook.Close
Workbooks("AA").Activate
Range("C3:E19").Value = 0
ActiveWorkbook.Save
ActiveWorkbook.Close
End Sub
I need code to check if the date in the last row of column F in my masterdata workbook equals the date right now in month and year.
If it is equal, delete all with this date and replace with new data.

you can try using the datediff function like :
' Index run through a column
For Index = 3 To 19
If DateDiff(Now, ActiveSheet.Cells(Index, 5)) = 0 Then
' Replace here your new data
End If
Next

I'll delete my "first answer", but here is my real answer to test:
Sub Send() 'asuming that this Sub is located in the "OriData"-Workbook
Dim OriData As Workbook
Set OriData = ThisWorkbook
Dim MasterData As Workbook
Set MasterData = Workbooks.Open("C:\Users\BB")
Dim ODSht As Worksheet
ODSht = OriData.Sheets("AA")
Dim MDSht As Worksheet
MDSht = MasterData.Sheets("CC")
Dim LastRow As Long
LastRow = MDSht.Cells(MDSht.Rows.Count, "a").End(xlUp).Row 'Last Row in Masterdata which contains data in Column a
Dim NewDate As Date
NewDate = MDSht.Cells(LastRow, 6) 'Last row, column F
If month(Date) = month(NewDate.Value) And Year(Date) = Year(NewDate.Value) Then
Maybe you'll have to delete the .Value after NewDate (You'll have to try).
As I am not sure what exactly you want to delete, I'll write the code that the whole row in masterdata gets deleted where in column F the date (month and year) is corresponding to the date of "today":
MDSht.Row(LastRow).Delete
If you want to delete more than just one line, you will have to change the code accordingly but maybe this will help you a little.
End If
MasterData.Save
MasterData.Close
Why in your code is the Range you're copying (A3:F19) and the Range you're setting to 0 (C3:E19) not the same??
OriData.Activate
ODSht.Range("A3:F19").Value = 0
OriData.Save
OriData.Close
End Sub
If you would make a function out of LastRow and NewDate you could loop it with new Data to control each time without further complications:
Function LastRow(WS As Worksheet)
LastRow = WS.Cells(WS.Rows.Count, "A").End(xlUp).Row
End Function
Function NewDate(Sht As Worksheet, R As Long)
NewDate = Sht.Cells(R, 6).Value
End Function
Following the If-Condition from before:
For DRow = 1 To LastRow(MDSht)
If (month(Date) = month(NewDate(MDSht, DRow))) And (Year(Date) = Year(NewDate(MDSht, DRow))) Then
MDSht.Row(DRow).Delete
ElseIf DRow = LastRow(MDSht)
MsgBox "Finished", vbokOnly
Exit Sub
End If
Next DRow
Tell me, if it worked and what did not (is interesting for me to know, and I can learn more from it), thank you :)

Related

how to copy past using VBA in excel?

Hellow,
I have a problem with copy past code
I can't identify the last cell in the row "where I would like to past" !!?
Here in the next code, I wrote "Shet.Cells(Rows.Count, "N").End(xlUp).row + 1", and it works well just in case there are no hidden rows, except that last row's value always replace itself !!
So, what should I do to update last row's value every time I execute Sub Copy_Past() ???
Sub Copy_Past()
Dim Shet As Worksheet
Set Shet = ThisWorkbook.Sheets(1)
Dim LRow As Long
'To get the latest cell in the column "N", where I would like to paste my data.
LRow = Shet.Cells(Rows.Count, "N").End(xlUp).row + 1
'To make a copy form where I selected
Selection.SpecialCells(xlCellTypeVisible).Copy ActiveSheet.Cells(LRow, "M")
'To delete the range of data that I selected and after coping them
Selection.SpecialCells(xlCellTypeVisible).Delete (xlShiftUp)
End Sub
I found a solution for this :)
I brought this method from here
https://answers.microsoft.com/en-us/msoffice/forum/msoffice_excel-msoffice_custom-mso_2007/finding-last-row-including-hidden-rows/af0d7d7c-84f1-44bf-b36a-5abc98a93fa6
Sub xlCellTypeLastCell_Example_Column()
For LastRow = Columns("N").SpecialCells(xlCellTypeLastCell).row To 1 Step -1
If Len(Cells(LastRow, "N").Formula) Then Exit For
Next
MsgBox LastRow
End Sub

Update start date by one day until end date as relevant data for each day within date range is recorded

I'm trying to update a date and simultaneously record each individual date and its respective z score on a separate worksheet. My excel file is is already set up so that as the date changes, the corresponding z scores for the day updates. Can anyone help me write VBA code that compiles the date with corresponding data for each day within the date range? Ideally, I want the code to adjust for a start date and end date when it is changed directly on the excel sheet. Unfortunately, I can't seem to update the date by one day without presetting it to a specific day, as an objected required error occurs for the "nextday" part of the code.
Sub compliedataloop()
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim wsprecip As Worksheet
Set wsprecip = wb.Worksheets("Precip")
Dim wshistoricaldata As Worksheet
Set wshistoricaldata = wb.Worksheets("Historical Data")
Dim nextday As String
Set nextday = wb.wsprecip.Range("CJ4")
wb.wshistoricaldata.Range("C4").Activate
wb.wsprecip.Range("CJ4").Activate
ActiveCell.Copy
wb.wshitoricaldata.Activate
ActiveCell.PasteSpecial
ActiveCell.Offset(1, 0).Activate
wb.wsprecip.Range("CN37").Activate
ActiveCell.Copy
wb.wshistoricaldata.Activate
ActiveCell.PasteSpecial
ActiveCell.Offset(-1, 1).Activate
wb.wsprecip.Range("CJ4").Activate
nextday.DateAdd = ("d")
Do While Enddate = False
'select, copy and paste first Date from cell CJ5 in "precip" Worksheet to "historicaldata" worksheet
wb.wsprecip.Range(CJ4).Activate
ActiveCell.Copy
wb.wshistoricaldata.Activate
ActiveCell.PasteSpecial
ActiveCell.Offset(1, 0).Activate
wb.wsprecip.Range("CJ4").Activate
nextday.DateAdd = ("d")
'copy new z-score for new date and paste data into "historicaldata" worksheet
wbs.wsprecip.Range("CN37").Activate
ActiveCell.Copy
wb.wshistoricaldata.Activate
ActiveCell.Offset(0, 1).Activate
ActiveCell.PasteSpecial
'reset positioning for next day's date in one cell above and to the right
ActiveCell.Offset(-1, 1).Activate
If Enddate = 2 / 28 / 2018 Then
Enddate = True
End If
End Sub
I don't know where to begin...
Make sure that you have Option Explicit as the first line in the module. It will require you to define all of your variables, which stops you from randomly mistyping (wbs) or using variables (Enddate) that haven't been assigned a value.
PS please you capital letters at the start of each word in variable names, so that you can read them easier i.e. NextDay
You defined nextday as a string. A string is not an object, hence why the " object required error occurs".
If all that you are doing is adding a day, you don't need the DateAdd function, just add 1.
You don't need to use any .Activate, .copy or .PasteSpecial to just copy a value from one cell to another.
I can't exactly figure out what you are doing; specifically with your end date. Are you trying to make this run once a day and keep writing to the next column? If so, you need to fine the last column with something like this:
Public Function LastColumn(Optional Row As Integer = 1, Optional Sheet As Excel.Worksheet) As Long
If Sheet Is Nothing Then Set Sheet = Application.ActiveSheet
LastColumn = Sheet.Cells(Row, Sheet.Columns.Count).End(xlLeft).Row
End Function
Set cell to the empty cell (Offset) after the last cell in row 4:
Set cell = LastColumn(4, wb.wsHistoricalData).offset(0,1)
Anyway, here is what your code roughly looks like when fixed...
Option Explicit
Sub ComplieDataLoop()
Dim wb As Workbook
Dim wsPrecip As Worksheet
Dim wsHistoricalData As Worksheet
Dim NextDay As Date
'Dim EndDate As Date???
Dim cell As Range
Set wb = ActiveWorkbook
Set wsPrecip = wb.Worksheets("Precip")
Set wsHistoricalData = wb.Worksheets("Historical Data")
NextDay = wb.wsPrecip.Range("CJ4")
'EndDate = ???
Set cell = wb.wsHistoricalData.Range("C4")
Do While EndDate < DateSerial( 2018, 2, 28)
cell = wb.wsPrecip.Range("CJ4")
Set cell = Offset(-1, 0)
cell = wb.wsPrecip.Range("CN37")
'reset positioning for next day's date in one cell above and to the right
Set cell = Offset(-1, 1)
'EndDate = ???
Loop
End Sub

Updating the sheets with other sheet

I am having three Sheets, Sht1 having my Basic data, sht2, having an data from last week, sht3 having an data with present week.
I am copying the data from sht1 to sht3, which ever has an Status red in columnJ.
After copying, i look into the lastweek sht and check for value in L and then fill the column N,O,P in sheet thisweek.
In the next step, whenever i click a button, the lastweeksht should be update by the data in present week sheet and present week should be deleted and evaluated with the new result. How can i do it. I should do the last step of moving the data to last week and updating thisweek to new result ? I am confused how to do this.
below are the codes, where i am using for copying the Status from Basic sht to this week and the vlookup formula i am using in thisweek.
Sub red()
Dim cell As Range
Dim nextrow As Long
Application.ScreenUpdating = False
For Each cell In Sheets("Red").Range("J5:J" & Sheets("Red").Cells(Sheets("Red").Rows.Count, "J").End(xlUp).Row)
If cell.Value = "rd" Then
nextrow = Sheets("ThisWeek").Cells(Sheets("ThisWeek").Rows.Count, "J").End(xlUp).Row
Rows(cell.Row).Copy Destination:=Sheets("ThisWeek").Range("A" & nextrow + 1)
End If
Next
Application.ScreenUpdating = True
End Sub
Sub lookup()
Dim tr As Long
Dim trsh As Long
tr = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
trsh = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
Sheets("ThisWeek").Range("M2:M" & tr).Formula = Application.WorksheetFunction.IfError(Application.VLookup(Sheets("ThisWeek").Range("L2:L" & trsh), Sheets("LastWeek").Range("$A:$P"), 13, 0), "")
End Sub
Sub lookupredaction()
Dim tr1 As Long
Dim trsh1 As Long
tr1 = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
trsh1 = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
Sheets("ThisWeek").Range("N2:N" & tr1).Formula = Application.WorksheetFunction.IfError(Application.VLookup(Sheets("ThisWeek").Range("L2:L" & trsh1), Sheets("LastWeek").Range("$A:$P"), 14, 0), "")
End Sub
Sub lookupredoverdue()
Dim tr2 As Long
Dim trsh2 As Long
tr2 = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
trsh2 = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
Sheets("ThisWeek").Range("O2:O" & tr2).Formula = Application.WorksheetFunction.IfError(Application.VLookup(Sheets("ThisWeek").Range("L2:L" & trsh2), Sheets("LastWeek").Range("$A:$P"), 15, 0), "")
End Sub
Sub lookupcomments()
Dim tr3 As Long
Dim trsh3 As Long
tr3 = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
trsh3 = Sheets("ThisWeek").Cells(Rows.Count, "A").End(xlUp).Row
Sheets("ThisWeek").Range("P2:P" & tr3).Formula = Application.WorksheetFunction.IfError(Application.VLookup(Sheets("ThisWeek").Range("L2:L" & trsh3), Sheets("LastWeek").Range("$A:$P"), 16, 0), "")
End Sub
this how the Basic data of my sheet Looks like. I always take the data from database and paste in this way
Image 1
First half is the Image of the second sheet. I call this sheet as last week. This sheet has an extra column E and F with Actions and no Actions evaluated. For now, this sheet is taken from the calculations of last week. in column G i have an formula, which calculates the CW. below is the sample Image of my third sheet, i call this as this week. In column G again i have an formula that calculates the CW. Here i use the first code, which always copy the Status with red to my this week.then, I use lookup codes to look into the ID in column A (as per dumy sheet) and copy the Actions and no Actions, accordingly.
Image 2
Now what i would like to have is, an button in my Basic sheet, and when i click the button, it should delete the last week and update the data of this week to last week . This week data should be deleted.
Later i have an button in my Basic sheet, which will include all the codes i have in the post and i could calculate for the new set of data. I have half done and left with other half struck how to achieve. Could someone help me achieve this. I would be thankful to you. and would improve myself with programing. Thank you in advance.
Posting this as an answer as it worked for you,
Use Range.ClearContents to clear the data in your lastweek sheet
Use Range.Copy Destination to copy the data from presentweek to lastweek
Clear the data in presentweek using clear contents.
You can use Sheets("ThisWeek").Range("A1:B10") (example) to operate different sheets with the same macro.

Excel: Click button to copy row onto another worksheet

I know, I know. There are a ton of suggestions how to solve that particular problem, but somehow they all tend to fail with me.
What I have (simplified): A (Mac) Excel-Sheet "Output" with:
Name Time Date
Mike 08:00 01.01.2016
The second row is yielding the data based on some input on yet another sheet.
What I need:
Whenever I will change the second row of "Output" (i.e. changing the input), I can click a button to add the entire second row onto a new worksheet "Log" (that will feature a header as well). Essentially logging the data upon clicking the button. The data can only be added once, multiple entries of the same data are deleted. After logging the data in "Log", the second row of "Output" does not need to be cleared, however I should not be able to add the same data again.
Any thoughts?
*EDIT
I modified the code from here: http://goo.gl/48jjDo.
Sub Submit()
Application.ScreenUpdating = False
Dim refTable As Variant, trans As Variant
refTable = Array("A = A2", "B = B2", "C=C2")
Dim Row As Long
Row = Worksheets("Log").UsedRange.Rows.Count + 1
For Each trans In refTable
Dim Dest As String, Field As String
Dest = Trim(Left(trans, InStr(1, trans, "=") - 1)) & Row
Field = Trim(Right(trans, Len(trans) - InStr(1, trans, "=")))
Worksheets("Log").Range(Dest).value = Worksheets("Output").Range(Field).value
Next
Application.ScreenUpdating = True
End Sub
*Edit2
Ok this got me further:
Sub CopyRangeFromSheet1toSheet2()
Dim lastRow As Long
lastRow = Sheets("Sheet2").Range("A100000").End(xlUp).Row + 1 ' then next free row in sheet2
Sheets("Sheet1").Range("A2:C2").Copy Destination:=Sheets("Sheet2").Range("A" & lastRow)
End Sub
However, how do I check now for multiple data? And I will need to paste only the values.
So far this works:
Sub CopyFormulas()
Dim sht1 As Worksheet, sht2 As Worksheet
Set sht1 = Sheets("Output")
Set sht2 = Sheets("Log")
sht1.Range("A2:C2").Copy
sht2.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
response = MsgBox("data was added")
End Sub
Not it is only the check for multiple entries that is missing

Hide rows based on the date

I am trying to keep the last 365 days visible in a micro tracking worksheet. As a new date gets inputted it would hide the first visible entry on the sheet so that only 365 cells are constantly displayed with the newest date at the bottom(ex Jan 15, 2015) and the oldest date at the top(Jan 15, 2014). When the user inputs Jan 16, 2015 it would hide Jan 15, 2014 so that the first entry is now Jan 16, 2014, and so on.
It has probably been about 15 years since I last used VBA but currently the code shown below will hide row 3 (where the first date and data is entered) but after that I can't get it to then hide row 4 once row 369 has text entered. Some insight into what I might be doing wrong would be greatly appreciated.
I would also assume that as this sheet became progressively larger it would start to slow down in opening or running smoothly so I would have to start fresh unless there is a way to make sure it always stays fast.
Dim i As Integer
Dim j As Integer
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
i = 3
j = 368
If Cells(j, j) = "" Then
Rows(i).Hidden = True
End If
i = i + 1
j = j + 1
End Sub
This is a completely different approach, but might suit you better in the long run.
Instead of hiding the rows to view what you are interested in. This approach uses two sheets.
Log Sheet: Contains all days
Report Sheet: Re-fills with only the last 365 days.
Setup Involved:
Set a second sheet up for your report, and give it the same headers as your Log Sheet.
Place the code provided in a module
If you want, you can add a workbook event so when the workbook opens, you can call this sub and have it update itself, or attach it to a hotkey or button.
This gives you plenty of room to create new formulas and charts to work over the set range of the report sheet. You can hide the Log Sheet.
Code:
Sub lastYearReportFill()
Dim lastRow As Long, lastCol As Long, lRow As Long, rRow As Long
Dim log As String, report As String
Dim today As Date, tempDate As Date
Dim daysTest As Long
log = "Log" 'Name your worksheets here
report = "Report"
today = Now
lastRow = Sheets(log).Range("A" & rows.count).End(xlUp).row
lastCol = Sheets(log).Cells(2, Columns.count).End(xlToLeft).column 'Using Header Row
For lRow = 3 To lastRow
tempDate = Sheets(log).Cells(lRow, 1)
daysTest = DateDiff("d", tempDate , today)
If daysTest = 365 Then
Exit For
End If
Next lRow
For rRow = 3 To 368
For lCol = 1 To lastCol
Sheets(report).Cells(rRow, lCol).Value = Sheets(log).Cells(lRow, lCol).Value
Next lCol
lRow = lRow + 1
Next rRow
End Sub
This should do the trick:
Sub HideRows()
Dim lngLastRow As Long
lngLastRow = Sheets("Sheet1").Cells(1, 1).End(xlDown).Row
If lngLastRow < 365 Then End
Rows(lngLastRow - 365).Hidden = True
End Sub
This is assuming that:
you are working in a sheet named "Sheet1" (if not, change the name in line 3 of the code accordingly)
the dates are in column A and start in row 1 (even the hidden ones). If the dates are in a different column, then change the second number in the cells(1, 1) statement to the number of the row. And if the dates do not start in row 1, change the first number of the cells(1, 1) statement to the row number of the first date.
And if you want to keep the row for the day exactly one year ago (as in, keep 1-15-14 on 1-15-15), you may need to change 365 in line 5 of the code to 366. This code also assumes that all other rows besides the one that was visible yesterday but doesn't need to be today are already hidden.
If you are concerned with speed, use Range AutoFilter Method which I answered HERE.
Applying it to your case:
Private Sub UpdateVisibleDates(sh As Worksheet, drng As Range)
With sh
Dim latest As Date
latest = .Range("A:A").Find("*", .Range("A1"), , , , xlPrevious).Value2
.AutoFilterMode = False
drng.AutoFilter 1, ">" & (latest - 365), xlAnd, "<=" & latest, False
End With
End Sub
Then just call it in your Worksheet_Change Event.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo halt
Application.EnableEvents = False
If Not Intersect(Target, Me.Range("A:A")) Is Nothing Then
Dim r As Range
Set r = Me.Range("A1:A" & Me.Range("A:A") _
.Find("*", Me.Range("A1"), , , , xlPrevious).Row)
UpdateVisibleDates Me, r
End If
forward:
Application.EnableEvents = True
Exit Sub
halt:
MsgBox "Error: " & Err.Number & vbCrLf & _
Err.Description, vbExclamation
Resume forward
End Sub
This is considering you have a complete date in Column A and your input doesn't skip dates.
But regardless, it will still hide dates not within the 365 date difference of the last entered date. HTH.