In excel VBA, I am looking for VBA code that adds a new line item with the latest month end each time the spreadsheet opens - vba

I currently have a spreadsheet that has individual line items for each month end. Starting in A1, 1/31/2021 and A5, 5/31/2021 for example. My goal is, each month when I open the spreadsheet, a new line item is created for that month; so if it's 5/21/2021 and I open the spreadsheet, it will create a line item with 5/31/2021. Is it possible to include logic that checks the current month I'm in and will open add a line item if it's relevant for the appropriate month?

Screenshot/here refer:
(note - for security reasons, linked sheet above has not VB code - this needs to be built in as described below).
High level
This soln. requires following: 2 named ranges, macro-enabled workbook. Office 365 not necessary.
Setup
Enter any date you wish in column A (max capacity = 100)
Ranges
Create named formula: Formulas | Name Manager | New… set name = 'dates'; enter formula: =$A$1:OFFSET($A$1,COUNTA(1,1000)-1,0,1,1)
(This is a dynamic (automatically grows to accommodate your list of dates in column A)
As for 2) but with following: name : 'Required' (w/ apostrophes), formula = =IFERROR(IF(YEAR(INDEX(dates,MATCH(MONTH(TODAY()),MONTH(dates),0)))=YEAR(TODAY()),0,1),1)
(this creates a formula that checks whether any of the dates in col A already have the current month. i.e. 'Required' = 0 if month already exists (for current year); else 1 returned)
VB
Let the fun begin!
Alt + F11 (open VB for Excel running on Windows)
Locate your file in the Project Explorer (typically default window pane on left hand side; if no such pane, then select from the upper ribbon/menu bar: View | Project Explorer:
Double click the component entitled 'ThisWorkbook' to reveal a new window pane on the right-hand side of the VB window.
The remaining operations appertain to the VB window pane on the Right Hand Side (RHS)...
There are two menu bars with drop-down functionality at the top of the VB-code pane:
Left drop-down / Right drop-down - select respective drop-downs as 'Workbook' and 'Open' respectively, then enter the code per below screenshot (code replicated here for convenience):
Code
Private Sub Workbook_Open()
REQ = Application.Evaluate("Required")
Range("f5").Value = REQ
If REQ = 1 Then
new_date = Format(Date, "dd/mm/yyyy")
Sheets("68516961").Range("dates").Offset(1).Value = new_date
End If
End Sub
Voila! You're all set to go! I tested a couple of times and all appears to be working fine. fyi - don't forget to save as macro-enabled workbook (I prefer .xlsb files as the typically have half the file size compared to .xlsm - the one exception I'm aware of is if there is an SQL connection - in which case it's about the same size as the .xlsm counterpart)...
Functionality:
Every time you open the workbook, the VB code is run - it checks to see if there are any dates that comprise the same month and year as the day your opening the file; if not, the date of 'that day' is automatically populated at the bottom of any existing list of dates in A:A. This gives you the freedom of being able to include other / manually entered dates or otherwise between successive VB created date appended values.
Appendices
Creating named ranges:

Related

Saving cell Presets in a dropdown list

At the moment I have created a spreadsheet which takes a bunch of inputs, runs them through a list of formulas, and then spits out the results onto a "report" worksheet.
I've been manually saving each of these reports as separate CSVs but I was hoping for a better method moving forward as it is getting quite tiring to have to open 10 CSVs when i do my monthly reports.
I am looking for a way to start saving all of these reports into a "database". My hope to to have one cell be for an user entry name and for two buttons. One to save the current report under the name entered by the user, and two to remove old records. I would then be able to revisit old entries by selecting them in the dropdown.
I've dabbled with VBA and Macros in the past but this is a little more complicated than what I've dealt with in the past. Looking for some help/direction.
Thanks for your time!
Depending on how your reports need to be used, you might find it satisfactory to simply make your data into one big Excel Table ( Insert Tab > Table ). When you do this, Excel will automatically fill-down any formulas that you enter in a column, and also show the formula using the headers instead of A1-style references.
I use this format, adding Y under Remove from Active List on each line that is already done. Then whenever I save the file or look at it for today's status, I filter out what's old and just look at the new. The other filters enable copy-pasting or printing whatever arrangement I like.
The filters and other things in the table can be referenced in VBA as Sheets("ThisSheet").ListObjects(1), which is an object with a number of useful properties and methods.
For VBA information, read more here: https://www.thespreadsheetguru.com/blog/2014/6/20/the-vba-guide-to-listobject-excel-tables
This is my code for auto-filtering the table to hide inactive items at time of save. You add it at ThisWorkbook in the VBA editor:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Sheets("Sheet1").Activate
SelectedCell = ActiveCell.Address 'this saves your screen selection for after the filtering
ActiveSheet.ListObjects(1).Range(1, 1).Select
If ActiveSheet.ListObjects(1).AutoFilter.FilterMode = True Then
ActiveSheet.ListObjects.Item(1).AutoFilter.ShowAllData
End If
A = ActiveSheet.ListObjects(1).Range.Rows(1).Find("Remove from List").Column - _
ActiveSheet.ListObjects(1).Range.Column + 1
ActiveSheet.ListObjects(1).Range.AutoFilter field:=A, Criteria1:="="
Range(SelectedCell).Select
End sub

Trouble with Copying VBA Code

I've been working on an independent project for a client of mine. They wanted to produce a button that, upon the user-click, it would open up a user-form and have a variety of macro-related options to choose from: a drop-down list, checkbox, option select button, etc.
I created a test formula and submitted it to the client; they enjoyed it thoroughly and decided to sent me a file to 'copy & paste' my original code within their excel file.
Problem is; because I'm a tad bit inexperienced with VBA I've run into a problem where once I click the button - the user form doesn't show up.
Below is a Dropbox link of the original file I created and it's original code; as well as the file that I am trying to copy.
Any help would be all welcome and appreciated.
Link to dropbox: https://www.dropbox.com/sh/l1t37lz8uritrua/AAAdWPGvw0GDZ6hW4SwmbBdRa?dl=0
OriginalProject.xlsm has a form named honor_roll_form which contains 100 lines of code.
CopyOfOriginal.xlsm has a form named UserForm1 which contains no useful code.
I do not believe there is any method of directly copying user forms from one workbook to another. Instead
Within VB Editor of OriginalProject.xlsm, select honor_roll_form.
Click File then Export File and save the form on your desktop or where ever you like.
You will now have two files on your desktop; one with an extension of frm and one with an extension of frx.
Within VB Editor of CopyOfOriginal.xlsm, click File then Import file.
Import honor_roll_form.frm
When I try clicking button "Honor Roll", I get "Method or data member not found" for project1Box. I will investigate after dinner (18:57 here) unless you tell me you already know why I am getting this error.
Extra comments in response to request from OP
It is late here but I have started looking down sub execute_button_Click within the second CopyOfOriginal.xlsm. I will comment on what I see even if it is not directly relevant to the non-execution of the macro.
If you open the VB Editor and look on the left you will see the Project Explorer. Near the top you will see:
Microsoft Excel Objects
Sheet1 (Sheet1)
I have always found this confusing. The first “Sheet1” is Excel’s Id for the worksheet and cannot be changed. The second “Sheet1” is the default name for the worksheet which can be changed. You can write Sheet1.Range("A1") or Worksheets("Sheet1").Range("A1"). That is: you can reference a worksheet by its Id or its name. You have named a variable of type Worksheet as Sheet1. Using Excel’s names as variable names can lead to bizarre errors so it is important to avoid doing anything like this.
It is better to always use meaningful names. At the moment, you know what Sheet1 means but if you come back to this macro in six or twelve months will you remember. I would use a variable as you have but I would name it WshtCis208 or WshtVBAProg or something similar.
Set ID = Range(Sheet1.Cells(2, 1), Sheet1.Cells(52, 1)) could be written as:
With WshtCis208
Set ID = Range(.Cells(2, 1), .Cells(52, 1))
End With
Using With statements produces faster code and, almost always, code that it easier to read.
“52” is the current bottom row for this table. Will you amend the macro for them every time they add or remove a student? There are several techniques for finding the last row, none of which is perfect in every situation. The technique that is the most convenient most of the time is:
Const ColCis208Id as Long = 1
Const ColCis208MidTermExam as Long = 5
Dim RowCis208Last as Long
RowCis208Last = .Cells(.Rows.Count, ColCis208Id).End(xlUp).Row
At the moment, column 1 is the Id column. It is perhaps unlikely that the Id column will move but it is very likely that some of the others columns will move when some new column is identified as useful. Do you want to scan the code trying to decide which 5s refer to the MidtermExam column when a Project3 column is added?
Constants allow you to name literals that might change. It makes your code easier to read and saves so much pain when a value changes.
.Rows.Count gives the number of rows in a worksheet for the current version of Excel so .Cells(.Rows.Count, ColCis208Id) identifies the bottom cell of column 1. End(xlUp).Row says go up until you hit a cell with a value and returns its row number. It is the VBA equivalent of Ctrl+Up.
The next statement subjectCount = … fails because projectBox does not exist on the form. You have changed the captions but not the names.
As far as I can see the form fails to execute because you have started updating it but have not finished.

Clicking Field with AutoIt in an ERP program

Here is my scenario:
I am starting AutoIT recorder. I record using the keyboard since using the mouse causes the script to stop most of the time or does something inaccurate when started after that.
What I do is I open up an Excel template I have created. I then go into an ERP system and copy a few columns which I paste into Excel. After these columns are inserted, a few more columns are calculated from the formulas I have previously inserted.
The problem is that when I am into the ERP system I have selected a specific time period...Let's say 1st November till 31st November. I then save the excel and use the Excel option to send an email to specific people with the excel report attached.
I compile the autoit script to an exe and I have a scheduler which starts the exe. The problem is that I need a way to change the date to December, then January and so on... How do I do that using AutoIt? Can it be done at all?
This is how the date looks like in the ERP program:
You need to first inspect the program using AutoIt Window Info tool: drag the target icon to the filed you wish to click on - use ControlClick. Let's take an example with Excel, it says the title is: "Book1 - Excel" and the ID of the button I chose is "1001", the script will be:
ControlClick("Book1 - Excel", "", 1001)
If there isn't any ID, it will be harder as you'll need to MouseClick by coordinates which is prone for errors...
Changing the time: in order to change the date picking according to the current month you'll need something like:
Local $stringInCell = ControlGetText("ERP title", "text in ERP window (can be empty)", controlID)
If #MON = StringLeft($stringInCell, 2) Then
ControlClick("ERP title", "text in ERP window (can be empty)", controlID)
EndIf
Where #MON is a macro, and StringLeft is like starts with, assuming the first 2 characters are good for you (e.g. January is 01).

How to format/color cells based on contents of other cells

I am trying to automate an Excel workbook to help save time in making employee work schedules. I have two sheets. Sheet1 contains a simple table used to create the intended schedule for the month (employee name in first column, dates on the top row, and every day is marked with "WORKING", "ON CALL", "OFF", etc.), and the other sheet contains a table with color codes to keep track of how well the schedule was actually kept as the weeks pass. I need Sheet2 to update the color codes based on the schedule manually planned on Sheet1 so I can waste less company time manually color coding cells.
I don't want to use Conditional Formatting, since I believe you can't overwrite the format it gives a cell (in the case an employee called out rather than coming in on his scheduled day to work and on Sheet2 this needs to be recorded - with a different color code). I just need help figuring out some macro that can help speed things up and waste less company time manually color coding cells.
I don't want to record a macro this time, since names and days working can/will be different every time the schedule is updated/made.
Here is something you can work on.
Right click on the sheet 1 tab and select "View Code" copy and paste this code there.
Change a cell in Column A in sheet 1 to A,B or C then go to sheet 2 and see what happened.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 1 Then
If Target = "A" Then Sheets("Sheet2").Range(Target.Address).Interior.ColorIndex = 3
If Target = "B" Then Sheets("Sheet2").Range(Target.Address).Interior.ColorIndex = 4
If Target = "C" Then Sheets("Sheet2").Range(Target.Address).Interior.ColorIndex = 5
End If
End Sub

Auto Updating Cell Values in Excel using VB

I have 2 Excel files named September and October. The September file contains values from which the October file refers/links to using the formula:
=+B2+'C:\\[September.xlsx]Sheet1'!A1
so cell B2 in October contains a value that is the sum of B2 and A1 which comes from the September file.
If I now create a November file, I would simply do a Save As on the October file and save the file as November.xlsx. However, this means that the November file is still referring to values September.xlsx. Is there any way of automatically updating the cells in November.xlsx to refer to October, either upon creation or opening of the November file?
i.e. so November's formula would automatically update to =+B2+'C:\[October.xlsx]Sheet1'!A1.
Or making a Window form pop up when opening the file, asking the month it would like it to link to, the user would then enter in a month then all the cells in range would be updated.
Is anyone able to point me in the right direction?
A simple find and replace will work with this kind of link.
You'll have to skip over cells that use the name as a label that you don't want to change. You can also do this in vba by looking only at formulas. Here is a post about how to do that.
You can use the Workbook.ChangeLink method.
expression.ChangeLink(Name, NewName, Type)
where Name is the existing file name, NewName is the new file name
To see it in action, try recording a macro while changing the link source manually, and examine the resulting code. Access it from Data/Connections/Edit Links menu
Probably the simplest implementation would be to write a macro to do the SaveAs and ChangeLink in one go. Or leverage the BeforeSave event.
Try recording a macro while you save your October workbook as November.xlsx and then editing the links in the new workbook to link to October.xlsx.
The raw code will be quite messy but you should be able to edit it to suit other months.
This purely formula-based solution works for me. It is spread across several cells. I imagine you could combine all the formulas in to one very long one in a singe cell, but in my view it's preferable not to. I would just tuck the intermediate cells (cells F12-F17 in my example) away somewhere out of the way.
The formulas:
Cell Formula
---- ---------------------------------------------------------
F12 =CELL("filename",A1)
F13 =MID(F12,FIND("[",F12)+1,FIND("]",F12)-FIND("[",F12)-1)
F14 =LEFT(F13,FIND(CHAR(1),SUBSTITUTE(F13,".",
CHAR(1),LEN(F13)-LEN(SUBSTITUTE(F13,".",""))))-1)
F15 =TEXT(DATE(2000,MONTH(DATEVALUE("1 " & F14))-1,1),"mmmm")
F16 =F15 & MID(F13,FIND(CHAR(1),SUBSTITUTE(F13,".",
CHAR(1),LEN(F13)-LEN(SUBSTITUTE(F13,".","")))),LEN(F13))
F17 =SUBSTITUTE(F12,F13,F16)
F18 =INDIRECT(ADDRESS(1,1,,,F17))
The results, assuming the current sheet is saved as December.xlsx:
Cell: Value:
----- ---------------------------------------------------------
F12 C:\Users\user.name\Documents\[December.xlsx]Sheet1
F13 December.xlsx
F14 December
F15 November
F16 November.xlsx
F17 C:\Users\user.name\Documents\[November.xlsx]Sheet1
F18 value from cell A1 in November.xlsx!
Notes:
F12 Gets full path of current workbook. May need to manually update calcs (press F9) for this cell to refresh
F13 Extracts filename from between '[' and ']' characters
F14 Removes extension (everything after last '.') to get the file's
base name (i.e. this month's name)
F15 Geta name of previous month
F16 Appends the extension that was removed earlier, to get filename of
previous month's sheet.
F17 Substitutes this filename into the current workbook's path. Here we
assume that this month's workbook is saved in the same folder
as the previous month's workbook.
F18 Gets value from row 1, column 1 (cell A1) in previous month's sheet