I am trying to create dates for each month individually. I have done my bit of work but looking for optimised code.
Steps
Create a Spreadsheet and change the name from "Sheet1" to "Year"
Column A ColumnB
2014 January
February
March
April
May
June
July
August
September
October
November
December
Now copy the below to VBA module
Sub GenerateDate()
Dim amonth As String
Dim col, cola As String
Dim ayear As Integer
For x = 1 To 12
Worksheets("Year").Select
Worksheets("Year").Activate
'//this will add every month worksheet
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = Cells(x, 2)
Worksheets("Year").Activate
'//get month name to string called amonth//
amonth = Cells(x, 2).Value
'//get year to variable type int called ayear//
ayear = Cells(1, 1).Value
'//activate month sheet
Worksheets(amonth).Activate
'//insert date 1st day of each month in cell A1
Cells(1, 1).Value = DateSerial(ayear, x, 1)
'//select 'A1' cell values
Cells(1, 1).Select
'// pass A1 value to a my_date
my_date = Cells(1, 1).Value
'//change the format of the date in A1 cell
Selection.NumberFormat = "d/mm/yyyy;#"
'//count number of days in month for the date in A1
numof_days = Day(DateSerial(Year(my_date), Month(my_date) + 1, 1) - 1)
'// col a and cola are two strings holds sting values "A" and "A1" respectively
col = "A"
cola = "A1"
'//Final value is range to be used to fill the dates
Final = col & numof_days
'//fill dates from A1 to Final cell values
With Range("A1")
.AutoFill Destination:=Range(cola, Final), Type:=xlFillDays
End With
'//auto fit the entire "A" column
Columns("A:A").EntireColumn.AutoFit
Next x
End Sub
My output
Creates new sheet for each month and generates dates for that month only.
As a first step you may find it more effective to add application.screenupdating = false at the beginning of your code and then application.screenupdating = true at the end. This will speed up your code. You may also consider doing the same for application.displayalerts.
Related
I've had a look around and can't find an actual answer to this.
I have a .csv to download every day. In it includes a text field 7+2 digits long. The 7 digits are in format CYYMMDD and the 2 digits are blank spaces.
This would be today's date: "1190729 " (without the quotes)
I've tried about 20 ways to convert this to a regular date, but I can't get every record to update properly
So far
The QueryTable uses type 2 (Text)
I =TRIM the text, place it back in the same location
I change the text into a recognisable date
"Paste as Text"
Then I get the same thing every time. Any date where the DAY is 13 or more, is a text field. 12 and under is a date field
The best way to fix it is to F2 but this is meant to be a totally automated report
I have tried changing dd/mm/yyyy to every other version I can think of (as for my excel m/d/yyyy is the default)
I've also tried moving .Value = .Value to the bottom, putting it in twice etc. but to no avail
Private Sub CopyDateTime(ByVal lastRowBeforeImport As Long)
Dim ws As Worksheet, ws2 As Worksheet
Dim tempsheet As String
Dim lastRowAfterImport, lastRowTemp
Set ws = Worksheets("Report")
'Bottom populated cell of Column "B"
lastRowAfterImport = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row
tempsheet = "temp"
Worksheets.Add
ActiveSheet.Name = tempsheet
Set ws2 = Worksheets("temp")
With ws.Range(ws.Cells(lastRowBeforeImport, 5), ws.Cells(lastRowAfterImport, 6))
'Copy new date and time to tempsheet'
.Copy Destination:=ws2.Range("A1")
End With
lastRowTemp = ws.Cells(ws.Rows.Count, 3).End(xlUp).Row
With ws2.Range(Cells(1, 3), Cells(lastRowTemp, 3))
.FormulaR1C1 = "=TRIM(RC[-2])"
.Value = .Value
.Copy Destination:=ws2.Range("A1")
.Delete
End With
With ws2.Range(Cells(1, 3), Cells(lastRowTemp, 3))
.FormulaR1C1 = "=RIGHT(RC[-2],2)&""/""&MID(RC[-2],4,2)&""/20""&MID(RC[-2],2,2)"
.Value = .Value
.NumberFormat = "dd/mm/yyyy"
End With
With ws2.Cells(1, 4)
.FormulaR1C1 = "=MID(TEXT(RC[-2],""000000""),3,2)&"":""&LEFT(TEXT(RC[-2],""000000""),2)&"":""&RIGHT(RC[-2],2)"
End With
'Delete tempsheet'
Application.DisplayAlerts = False
'Worksheets(tempsheet).Delete
Application.DisplayAlerts = True
End Sub
If you have "1190729 " in A2 then the formula
=DATE(2000+(MID(A2,2,2)),(MID(A2,4,2)),(RIGHT(TRIM(A2),2)))
will produce the date 29th July 2019 in your current date format
From MSDN:
Date variables are stored as IEEE 64-bit (8-byte) floating-point
numbers that represent dates ranging from 1 January 100, to 31
December 9999, and times from 0:00:00 to 23:59:59.
Your VBA function may parse well string formats from CSV, but you are creating a string value which is not a proper Excel data type for dates.
Use =DATEVALUE function to convert the string representation of the DATE (ex. 29/7/2019) to the actual Excel date.
For example in your case: cell.Value = DATEVALUE(TRIM(RC[-2]))
Once in the proper data type, you can change the date format using the NumberFormat property.
More about DATEVALUE from MSDN.
I have a list of ascending dates. I am using the following formula to return the cell reference:
=CELL("address",INDEX(A2:A14,MATCH(D1,A2:A14,1)))
This formula gives me the result I what e.g. a search for 1/2/2017 returns the cell reference of $A$6. While a search for 12/30/2016 returns the cell reference of $A$4.
How would I accomplish the same result using VBA, while returning the next date value in the list if the search date is greater than the previous date in the list and another date that is greater than the search date exist?
Dates 1/2/2017
12/27/2016 $A$6
12/28/2016
12/29/2016
1/1/2017
1/2/2017
1/3/2017
...
If i anderstood your question i have an alternative for you.
I have tested this code and works fine.
I have a list of ascending dates from A2 to A14
I use cells(1,4) [in the sheet is D1] as input data to compare into list.
The result of comparison is into cells(2,4) [in the sheet is D2]
i.e.
my list from A2 to A14
12/27/2016
12/28/2016
12/29/2016
01/01/2017
01/02/2017
01/03/2017
01/04/2017
01/05/2017
01/06/2017
01/07/2017
01/08/2017
01/09/2017
01/10/2017
into cells(1,4) i wrote 01/05/2017
output macro is into cells(2,4) and is :$A$9
If i write 01/11/2017 the result is $A$14
Sub test()
Dim i, start, finish As Integer
Dim myDate,output As Date
i = 0
start = 2
finish = 14
myDate = Cells(1, 4) ' my input - cells(2,4) is output
For i = finish To start Step -1
If (i = start) Then
Cells(i, 1).Activate 'cell where is "my date"
Cells(2, 4) = ActiveCell.Address ' get the address -output
'Exit For
End If
If myDate >= Cells(i, 1) Then
Cells(i, 1).Activate 'cell where is "my date"
Cells(2, 4) = ActiveCell.Address ' get the address -output
Exit For
End If
Next i
End Sub
Users can enter a date in column B freely like so:
(Dates in uk format)
Column B
02/01/2017
02.01.2017
01.01.17
01012017
010117
Its extremely frustrating when we want to run a report that these date formats are not consistent.
I am trying to create a code which will format the date, however it's entered with slashes like so:
02/01/2017
02/01/2017
01/01/2017
01/01/2017
etc...
Here is my code:
Dim Cell As Range, CellVal As String
If Not Intersect(Target, ActiveSheet.Columns("B")) Is Nothing Then
For Each Cell In Intersect(Target, ActiveSheet.Columns("B"))
CellVal = Cell.Value
If (Not CellVal Like "*[!0-9]*") And (Len(CellVal) > 4) Then
CellVal = Format(CellVal, "## ## ##")
Cell.Value = CDate(WorksheetFunction.Replace(CellVal, 4, 2, MonthName(Mid(CellVal, 4, 2))))
Cell.NumberFormat = "dd/mm/yyyy"
End If
Next Cell
End If
This only seems to work if the user enters a 9 digit format like so:
01012017
This is then changed to
01/01/2017
But if the user enters
010117
Then this translates to:
28/01/1955 <---This is wrong
The other thing, users may enter dots:
01.01.2017
Then the code just doesn't work at all.
Please can someone show me a better way to do this?
Just keep it simple and obvious...No?
Dim Cell As Range, CellVal As String, dim Dt as Date
If Not Intersect(Target, ActiveSheet.Columns("B")) Is Nothing Then
For Each Cell In Intersect(Target, ActiveSheet.Columns("B"))
val = Cell.Value
if instr(val,".")>0 then 'check if this particular char is present
temp = split(val,".")
day= temp(0)
month=temp(1)
year=temp(2)
Dt = DateSerial(year, month, day)
Cell.Value= Format(Dt, "dd/mm/yy") 'you can change this to "dd-mmm-yyyy" or whatever
else if instr(val,"/")>0 then
temp = Split(val,"/")
day= temp(0)
month=temp(1)
year=temp(2)
Dt = DateSerial(year, month, day)
Cell.Value= Format(Dt, "dd/mm/yy")
else if len(val) = 8 then
day = left(val,2) ' start at first, and take 2
month = mid(val, 3,2) 'start a 3rd char and take 2
year = right(val,4)
Dt = DateSerial(year, month, day)
Cell.Value= Format(Dt, "dd/mm/yy")
else if len(val) = 6 then
day = left(val,2) ' start at first, and take 2
month = mid(val, 3,2) 'start a 3rd char and take 2
year = right(val,2)
year = year +2000
Dt = DateSerial(year, month, day)
Cell.Value= Format(Dt, "dd/mm/yy")
end if
Next Cell
End If
I could have make some mistakes in func. parameters here, because it's 1:30 in the morning, and I dont have excel at my laptop, but I think I got right the main part :)
I'm trying to find a way to automatically insert a column based on a date. Here's some context:
The top row of my spreadsheet (Row 1) contains dates in the format yyyy/mm/dd
The dates aren't day-by-day; they are weekly (i.e. one cell may say 2015/09/21 the next will say 2015/09/28 and the next will say 2015/10/05) so this can change from year to year
I need to find a way to automatically insert ONE column at the end of each quarter and TWO columns at the end of each half (i.e. ONE column between March and April, TWO between June and July, ONE between September and October, and TWO between December and January)
So far, this is what I am using to traverse the top row and see if the date is before October but after September. The dates start from cell I1. Although the code executes without any error, it does not actually do anything. Any help you all can offer will be appreciated.
With Sheets("Sheet1")
Range("I1").Select
Do Until IsEmpty(ActiveCell)
If ActiveCell.Value < DateValue("2015/10/1") And ActiveCell.Offset(0, 1).Value > DateValue("2015/9/28") Then
Range(ActiveCell).EntireColumn.Insert
End If
ActiveCell.Offset(0, 1).Select
Loop
End With
I think you're off to a good start with your method. You should be able to just check if the day of the month is less than or equal to 7. That should indicate the first week in a month. If that month is 4 or 10, insert a column. If it's 1 or 7, insert two.
Dim r As Range
Set r = Range("I1")
Do Until IsEmpty(r)
If Day(r) <= 7 Then
Select Case Month(r)
Case 4, 10
r.EntireColumn.Insert
Case 1, 7
r.Resize(1, 2).EntireColumn.Insert
End Select
End If
Set r = r.Offset(0, 1)
Loop
Going strictly on a change in months bewteen two cell in the header row may be the easiest logic.
Sub insert_quarter_halves()
Dim c As Long
With Worksheets("Sheet8") 'set this worksheet reference properly!
For c = .Cells(1, Columns.Count).End(xlToLeft).Column To 2 Step -1
If (Month(.Cells(1, c - 1).Value2) = 3 And Month(.Cells(1, c).Value2) = 4) Or _
(Month(.Cells(1, c - 1).Value2) = 9 And Month(.Cells(1, c).Value2) = 10) Then
.Cells(1, c).EntireColumn.Insert
ElseIf (Month(.Cells(1, c - 1).Value2) = 6 And Month(.Cells(1, c).Value2) = 7) Or _
(Month(.Cells(1, c - 1).Value2) = 12 And Month(.Cells(1, c).Value2) = 1) Then
.Cells(1, c).Resize(1, 2).EntireColumn.Insert
End If
Next c
End With
End Sub
When inserting columns, always travel from right to left or you risk skipping an entry that was pushed forward.,
Disclosure: I'm fairly inexperienced at coding of most sorts but have a reasonable understanding of the logic behind it and quite often just need a little push with getting syntax's right etc.
What I'm trying to do is create a spreadsheet where across the top row is a list of consecutive dates. In the first few columns is data for bills etc. What I want my macro to do is look at the amount of a bill, the start and end dates and the frequency of the bill (weekly/monthly etc) and then populate the cells in that same row in the columns of the dates where the bill is due. I've spent the last day coming up with this code and I was pretty happy with it until I went to run it. I've already got rid of a few bugs where I was using a variable.Value which apparently doesn't exist but now I'm up against some issues outside of my grasp. And I've had no luck searching the internet.
The first problem that the debug finds is on this line:
currentDate = Cells(G, currentRow).Value 'Set Start Date
I'm getting a Run-Time Error '1004': Application-defined or Object-defined error. I'm sure that it's just a simple syntax problem or something. What that line is supposed to be doing (in the first instance) is looking at the Start Date in Cell "G3" which is formated as a date (04-Feb-14) and assigning the variable currentDate to that date so that I can then do a search across all the dates in the first row for that 'currentDate'.
Am I being clear enough? My code is below.
My Code:
Private Sub CommandButton1_Click()
Dim currentDate As Date
Dim currentRow As Integer
Dim repeatuntilDate As Date
Dim repeatuntilRow As Integer
currentRow = 3 'First row of entries
repeatuntilRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row 'Last row of entries
While currentRow < repeatuntilRow 'Loop from first row until last row of entries
currentDate = Cells(G, currentRow).Value 'Set Start Date
repeatuntilDate = Cells("H,currentRow").Value 'Set End Date
While currentDate <= repeatuntilDate 'Loop from Start Date until End Date
dateAddress = Range("J1:AAI1").Find(currentDate, LookIn:=xlValues).Address 'find the current date within the range of dates in row 1
Cells("dateAddress.Column,currentRow").Value = Cells("D,currentRow").Value 'Populate cell with amount
'Increment the currentDate by the chosen frequency
If Cells("E,currentRow").Value = "Weekly" Then
currentDate = DateAdd("ww", 1, currentDate)
ElseIf Cells("E,currentRow").Value = "Fortnightly" Then
currentDate = DateAdd("ww", 2, currentDate)
ElseIf Cells("E,currentRow").Value = "Monthly" Then
currentDate = DateAdd("m", 1, currentDate)
ElseIf Cells("E,currentRow").Value = "Quarterly" Then
currentDate = DateAdd("q", 1, currentDatee)
ElseIf Cells("E,currentRow").Value = "6 Monthly" Then
currentDate = DateAdd("m", 6, currentDate)
ElseIf Cells("E,currentRow").Value = "Annually" Then
currentDate = DateAdd("y", 1, currentDate)
' ElseIf Cells("E,currentRow").Value = "Once off" Then
' Exit While
End If
Wend
currentRow = currentRow + 1 'Once row is complete, increment to next row down
Wend
End Sub
to answer why you get Object Defined Error you missed the Cells property syntax which is:
Cells(row_index, col_index) which accepts long data type (numbers).
So it should be:
currentDate = Cells(currentRow, 7).Value 'G is the 7th column
But similarly you can refer to the col_index argument like this:
currentDate = Cells(currentRow, "G").Value 'take note of the qoutation marks ""