Hide rows based on the date - vba

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.

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

VBA merge non-adjacent cells containing same text in Excel

I am building a calendar in Excel that automatically maps event information from a table to a dynamic calendar view. Each row represents a time from 8AM - 6PM, and each column represents a day of the week from Sunday - Saturday. I was able to map information for each unique event to two separate cells in each column, one for start time and one for end time. I am looking for help with building a macro to merge the cells containing the same information into one so the calendar is cohesive. E.g. Event A starts at 9AM and ends at 11AM. There is currently one cell populated at 9AM and one at 11AM, but the cell for 10AM is blank and I'd like to merge the two populated cells from the 9AM cell to 11AM cell. As the populated cells will not always be adjacent, the offset function doesn't seem to work in this case.
Here is the pseudo code I'm trying to accomplish:
For each column in a specified region
loop through each row
if two cells contain identical text
merge those two cells
Here is the little bit of code I've managed to come up with so far. You can tell there are many gaps and probably syntax errors:
Sub MergeCells
Dim cells As String
cells = ActiveSheet.Range("C8:V28,C31:V51,C54:V74,C77:V97,C100:V120")
If ActiveSheet.Range(cells).??? Then
ActiveSheet.Range(cells).Merge
End If
End Sub
Any help would be greatly appreciated!
Before picture
After picture
Okay - this may be overkill, and you may need to tweak, but this was fun to work on.
Sub combine_Same()
Application.DisplayAlerts = False
Dim tableRng As Range
Dim i As Long, k As Long, lastRow As Long
Dim curText As Range, prevText As Range
Dim tableRanges As Variant
tableRanges = Split("b3:e20,C31:V51,C54:V74,C77:V97,C100:V120", ",")
Dim rng As Long
For rng = LBound(tableRanges) To UBound(tableRanges)
Debug.Print "Working with: " & tableRanges(rng)
Set tableRng = Range(tableRanges(rng))
' tableRng.Select
lastRow = tableRng.Rows(tableRng.Rows.Count).Row
For k = tableRng.Columns(1).Column To tableRng.Columns.Count
For i = lastRow To tableRng.Rows(1).Row Step -1
Set curText = Cells(i, k)
Set prevText = curText.End(xlUp)
If curText.Value = prevText.Value And Not IsEmpty(curText) Then
'curText.Select
Range(curText, prevText).Merge
curText.VerticalAlignment = xlCenter
ElseIf curText.Value = curText.Offset(-1, 0).Value And Not IsEmpty(curText) Then
'curText.Select
Range(curText, curText.Offset(-1, 0)).Merge
curText.VerticalAlignment = xlCenter
End If
Next i
Next k
Next rng
Application.DisplayAlerts = True
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.

Compare two cells, if equal then delete and replace

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 :)

Excel VBA: hide/unhide columns in day-over-day tracker, skipping weekend columns

Simple in concept hard to implement. Been trying all day with no luck.
I have a day=over-day tracker. With each new day I would like to be able to run a macro that hides the previous day and unhides the current day. I have 10 days showing at a time (current day + 9 previous).
Through Googling, I was able to find some good code that functions as I describe except that it does not skip a column (which I would need to have occur if I want to essentially skip over weekend days in my tracker).
Thanks for your help.
sub whatever()
dim i as long
for i = 4 to 34
if columns(i).hidden = false then
bfirst = true
columns(i).hidden = true
columns(i + 10).hidden = false
exit for
end if
next
end sub
If your data has a row of Dates, you can indeed use Weekday(Cells(r,c)) to determine if its a weekend, then use Select Case to hide/unhide columns.
The current can be retrieved by Date().
Then you can set to codes in Sub Workbook_Open() in ThisWorkbook object. So when the file is opened, it runs the code so today and 9 previous days are not hidden.
EDIT: Add these 2 sub into "ThisWorkbook" object, change as per your sheet name, row and column. If you are to want 9 previous "Weekdays", then you will have to change the Case or use different approach to determine whether a column should be hidden or not. This is as far as I will go. Good luck!
Sub Workbook_Open()
ShowTodayPlusPrevious
End Sub
Private Sub ShowTodayPlusPrevious()
' Assuming Row 1 contains the dates, stating from column 2
Const DateRow As Long = 1
Const PrevDays As Long = 9
Dim oWS As Worksheet, lCol As Long, lLastCol As Long, bHide As Boolean
Set oWS = ThisWorkbook.Worksheets("Sheet1") ' Change this to the name of your sheet
lLastCol = oWS.Cells.SpecialCells(xlLastCell).Column
For lCol = 2 To lLastCol
bHide = True
Select Case Date - oWS.Cells(DateRow, lCol).Value
Case 0 To PrevDays
If Weekday(oWS.Cells(DateRow, lCol).Value) <> vbSaturday And _
Weekday(oWS.Cells(DateRow, lCol).Value) <> vbSunday Then
bHide = False
End If
End Select
oWS.Columns(lCol).Hidden = bHide
Next
Set oWS = Nothing
End Sub