Generate workbook unique ID from template in Excel - excel

In my organization we have an Excel template that all employees have to fill frequently. This template originates hundreds/thousands of Excel files (workbooks) per year.
For the sake of organisation, I urgently need to have a unique ID for each of these files (i.e. unique ID per workbook generated by this template).
Currently, my idea is to generate the following ID in a cell of the workbook:
[user]-[YYYYMMDD]-[hhmmss]
in which:
user is a string representing the username of the employee which would be filled in by the user. So no problem here.
YYYYMMDD is year, month and day
concatenated
hhmmss is hour, minute and second concatenated
For this effect, I would need that my Excel template automatically fills a cell with the YYYYMMDD-hhmmss information with the exact date and time of generation.
This information should be created once the template generates the workbook, and cannot be changed ever after. So these should be values in a (protected) cell and not a formula (I guess).
I cannot figure out how to do this after searching for a long time. I am not sure if it is needed or not, but I am no master of VBA.

The idea of having a date/time field is good .... create a workbook smilar to this
add the following code to the ThisWorkbook module:
Private Sub Workbook_Open()
If [B2] = "" Then
' timestamp
[B2] = Now()
' suppress warning when saving macro containing workbook in non-macro format
Application.DisplayAlerts = False
' save under calculated name
ActiveWorkbook.SaveAs [B1] & "-" & Format([B2], "YYYYMMDD-hhmmss")
' turn on alerts again
Application.DisplayAlerts = True
End If
End Sub
and save as a macro enabled template
Then create a [File - New] from this template .... it will immediately be saved under the name of the user with macros removed so that the code can't hit it another time.
The user name could be retrived from the environment or from the registry.
Alternatively you can examine if the file has a true name or (still) is named Book nnn which means it hasn't been saved before; this removes the need to reserve a timestamp cell in your workbook

Here are a couple of functions you could use to get your id. If you put this inside a vba module on your template you will be able to call the functions from the worksheets or other vba code (e.g. in workbook just enter '=get_id()', in vba you would do something like 'id = get_id()' to call this:
Option Explicit
Public Function lpad(string1, padded_length, _
Optional pad_string = " ")
Dim chars
chars = padded_length - Len(string1)
lpad = WorksheetFunction.Rept(pad_string, chars) & string1
End Function
Public Function get_id()
Dim user
Dim YYYYMMDD
Dim hhmmss
user = Environ("username")
YYYYMMDD = Year(Now()) & lpad(Month(Now()), 2, 0) & lpad(Day(Now()), 2, 0)
hhmmss = lpad(Hour(Now()), 2, 0) & lpad(Minute(Now()), 2, 0) & lpad(Second(Now()), 2, 0)
get_id = user & "-" & YYYYMMDD & "-" & hhmmss
End Function
The lpad function is just for formatting (so that you get 07 for July instead of 7 etc.). I have also added something here to set the user to the windows environment variable for the current user's name, but if you want to promt the user instead this part could easily be replaced.
Let me know if you have any questions.

Related

Multiple language date formats in Excel with VBA

I'm trying to have the current date recognized in Excel using an =TEXT(TODAY(),"mmmm d yyyy") function, but I have run into issues with Canadian users based in Quebec, who may have a system install set to English or French, and likewise an Office install in one language or the other. For today's date, my spreadsheet pulls March 10 2021 on my computer, but the result has been askew for each Quebec-based user I have tested with.
In order to resolve this, I set up a VBA function to pull the application's language setting, with the intention to use a simple IF to check the language code and change from "mmmm d yyyy" to "mmmm j aaaa" (the letters to match the French journée for day and année for year, as per consulting the formats available on French Excel's TEXTE function). My function worked... but the output has come back incorrect each time.
Public Function LangCheck()
Dim lang_code As Long
lang_code = Application.LanguageSettings.LanguageID(msoLanguageIDUI)
LangCheck = lang_code
End Function
So that did its job, but the outputs should have been March 10 2021 or mars 10 2021. Instead from two different users I have received:
March j Wednesday, from a user with a French Excel setting, confirmed by the code outputting language ID 1036.
mars d yyyy, from a user with an English Excel setting on a French OS, confirmed by the code outputting language ID 1033.
Excel is translating every function to its French cognate, but won't translate the formats for the TEXT function on its own. Does anyone have a suggestion for a VBA or function-based solve to this conundrum so that I can ensure consistent dates return regardless of language?
You can use the Application.International properties to extract the correct DMY tokens, and use a named reference for the text function format code:
Change your formula to:
=TEXT(TODAY(),"dtFormat")
And store the below code into the ThisWorkbook module
Wherever the file is opened, the Sub will run and ensure that the dtFormat name has the appropriate DMY codes for the locale.
Option Explicit
'change text function date code
Private Sub Workbook_Open()
Dim yrCode As String, mnthCode As String, dyCode As String
Dim dtCode As String
Dim nM As Name
With Application
yrCode = WorksheetFunction.Rept(.International(xlYearCode), 4)
mnthCode = WorksheetFunction.Rept(.International(xlMonthCode), 4)
dyCode = WorksheetFunction.Rept(.International(xlDayCode), 1)
End With
'Can only add a name if it is absent
For Each nM In ThisWorkbook.Names
If nM.Name = "dtFormat" Then
nM.Delete
Exit For
End If
Next nM
dtCode = mnthCode & " " & dyCode & " " & yrCode
ThisWorkbook.Names.Add _
Name:="dtFormat", _
RefersTo:="=""" & dtCode & """", _
Visible:=False
End Sub

How to make unique filename when saving Excel worksheet in VBA

I have a spreadsheet that is my template that everyone accesses. The first button I want them to hit is my Macro "Save As" button that saves in the correct spot on my SharePoint.
This works great! BUT... it overwrites without warning.
I would like to 1 - make sure it never overwrites - I would prefer it cancel the process without saving over something.
Second, I would prefer that it saves it as "[predetermined name]_copy01" where 01 can go to 99 in case the button gets tapped again by someone else after the sheet is completed by the original person (thus ruining that first person's day).
Here is my current code - how do I at least get a pop up for overwriting, and even better, get the renaming for copies (I am assuming this is some sort of "if" or "if/else" statement)
Sub Save_Workook_NewName()
Dim tillDay As Date
If Time < 11 / 24 Then
tillDay = Date - 1 + 11 / 24
Else
tillDay = Now
End If
Application.AlertBeforeOverwriting = True
Dim path As String
path = "https://ourcorporatesite.sharepoint.com/sites/tills/Shared%20Documents/Nightly%20Tills/"
ThisWorkbook.SaveAs FileName:=path & Format(Now(), "yy-mm-dd") & "_Tills.xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled, ReadOnlyRecommended:=False
End Sub
For making a unique file name, I am using the Username of the Excel user and the current time stamp. Thus, it makes sure that every user generates a different file name, always. Just make sure that the code runs more than 1 second (or add the 1 second wait in the name generator):
Public Function GenerateName() As String
GenerateName = Format(Now(), "yyyy_mm_dd_hh_MM_ss") & "_" & Environ("Username")
End Function
In this case, if you want to save the file it is the following: 2019_11_14_22_08_50_vityata. As a bonus, it could be easily sorted by date created.
It could be called like this:
ThisWorkbook.SaveAs Filename:=Path & GenerateName & ".xlsm"

Create a new workbook from an Excel template located in a different folder

I have an Excel 2016 spreadsheet which contains the details of quotes sent to Customers (1 row for each quote containing cells with the Customer Name, Quote Date, Quote Number etc). I am trying to design a macro to reside in this spreadsheet that will create a new workbook based on an existing Excel template (UK - Quote Sheet.xltm), populate certain fields in the new workbook and save it with a filename name constructed from elements of quote entry. For example, if the spreadsheet contains an entry of 19/11/18 in the Date Cell, ABC in Customer Name field and Q1234 in the Quote Number field, the new file will be given the name "Q1234 - ABC (19.1.18).xlsm" and the Date, Customer Name and Quote Number will be inserted into the appropriate Worksheet cells in the new workbook. I have been able to get the macro to generate the appropriate filename and populate the cells in the new workbook but only by using absolute file paths for both the location of the template and the location of where the new workbook is to be stored. This is fine so long as the folder paths are the same on every PC I need to run the macro but this isn't the case so the macro fails when it's run on a PC where the file paths are different. Whilst the folder structure on every PC will be:
..\Documents\Quotes\Quotes Database for the location of Quotes details spreadsheet
..\Documents\Templates\Quotes for the location of the template file
..\Documents\Quotes\Amendable Quotes for location of the new workbook
the location of this folder tree will vary by PC.
The following code works for when the above folder tree resides inside C:\VD Operations but I need to modify so that it works no matter where the folder tree resides e.g. it could be under D:\Work\VD Operations:
Sub CreateQuote() 'Generate a new quote using UK - Quote Sheet Template
Dim qContact, qNo, qDate, qCustomer As String
Dim qFilename As String
Dim qDay, qMonth, qYear As String
Dim qNewWorkbook As Workbook
Dim qDest As Worksheet
' Get quote details from appropriate entry in Quote Database
qContact = Cells(ActiveCell.Row, 13).Value
qNo = Cells(ActiveCell.Row, 1).Value
qCustomer = Cells(ActiveCell.Row, 12).Value
qDate = Cells(ActiveCell.Row, 3).Value
qDay = Day(qDate)
qMonth = Month(qDate)
qYear = Right(Year(qDate), 2)
Set qNewWorkbook = Workbooks.Open(Filename:="C:\VD Operations\Documents\Templates\Quotes\UK - QUOTE SHEET.xltm", _
Editable:=False)
' Construct quote file name
qFilename = "C:\VD Operations\Documents\Quotes\Amendable Quotes\" & qNo & " - " & qCustomer & " (" & qDay & "." & qMonth & "." & qYear & ").xlsm"
' Update Cover sheet in quote with values from Quote Database
Set qDest = qNewWorkbook.Sheets("Cover Sheet")
qDest.Range("QuoteNo") = qNo
qDest.Range("Customer") = qCustomer
qDest.Range("Contact") = qContact
qDest.Range("QuoteDate") = qDate
' Save the quote
qNewWorkbook.SaveAs Filename:=qFilename, FileFormat:=52
End Sub
I know I can find the path of the Quote details spreadsheet but not sure how to use this to calculate the path to the other files.
For this folder structure (for example):
C:\
_Stuff\
test\
tmp1\ '<< macro file is stored here
tmp2\ '<< need to load a file "test.xlsx" from here
You can do this:
ThisWorkbook.Path '>> C:\_Stuff\test\tmp1
ThisWorkbook.Path & "\..\tmp2\test.xlsx" '>> C:\_Stuff\test\tmp2\test.xlsx
so the .. takes you "up" to C:\_Stuff\test and from there you can go "down" to tmp2

Numeric Values Change During Access VBA DoCmd.TransferSpreadsheet

I'm developing a module to automatically import Excel worksheets into an Access table. The design of the worksheets being imported are identical. Using DoCmd.TransferSpreadsheets imports columns A-O (a mix of text and numeric data) well, however the values for columns P-AD have issues...
Column P and Q represent beginning and ending odometer values with R their elapsed distance. For example, on the worksheet Vehicle OHS-11 is reported as beginning at 154952, ending at 155636, for an elapsed distance of 684. The imported record shows as beginning AND ending at 155636, for an elapsed distance of 0.
Columns S-AA just refuse to import at all. Column AB imports 0 for all records including those with legitimate values (i.e., not null). Columns AC-AD sporadically import a 0, but many records are blank. See the figure below:
I've tried to no avail:
setting the field types in Access
letting Access create the table from scratch
DoCmd.RunSavedImport isn't ideal since the source spreadsheets have different names
a SELECT * INTO will create a new table for each worksheet and I am needing to consolidate the data from all spreadsheets to a single table
It is peculiar that the imports are successful without transfer error tables being created but yet the values are being ignored/swapped. Should it matter, the cells in columns E-P, R and AB-AD are formulas.
I am using Excel 2016 and Access 2016 on a Windows 10 tablet system. Here is the code:
Option Compare Database
Sub Import_New_WS()
'--- Import new worksheets to temporary table
Dim dbAC As Database
Dim rsList, rsMonth, rsXfer As Recordset
Dim strDestPath, strFilePath, strMFRSheetNo, strRange As String
Set dbAC = CurrentDb()
Set rsList = dbAC.OpenRecordset("SELECT * FROM [XFER_LIST_ONLY_LATEST_MFR]")
Set rsMonth = dbAC.OpenRecordset("SELECT * FROM [FP_MO_CAL_MO]")
'Set rsXfer = dbAC.OpenRecordset("SELECT * FROM [XFER_WS]")
If rsList.EOF = True Then Exit Sub 'Checks that there are worksheets to process
'--- Delete existing records from MFR consolidation table
'DoCmd.SetWarnings False
'DoCmd.RunSQL "DELETE * FROM [XFER_WS];"
'DoCmd.SetWarnings True
'--- Import worksheets into consolidation table
rsList.MoveFirst
strMFRSheetNo = Right(CStr(rsList.Fields("MFR_LAST_FP")), 2)
Do Until rsList.EOF
rsMonth.FindFirst "FISCAL_MO = " & strMFRSheetNo
strRange = rsMonth.Fields("WS_NAME") & "!A2:AD" & Format(rsList.Fields("NO_ROWS") + 1, "0")
strFilePath = rsList.Fields("FILE_PATH")
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, "XFER_WS", strFilePath, False, strRange
strDestPath = "I:\Dept\DCS\MPOOL\Fleet Management Data\MFR\MFR FY " & Mid(CStr(rsList.Fields("MFR_LAST_FP")), 3, 2) & _
"\" & Mid(strFilePath, 81, Len(strFilePath))
Debug.Print strDestPath
'FileCopy strFilePath, strDestPath
'Kill strFilePath
rsList.MoveNext
Loop
Set dbAC = Nothing
Set rsList = Nothing
Set rsXfer = Nothing
Set rsMonth = Nothing
DeleteImportErrorTables
End Sub
After much research and testing multiple strategies to address this issue I simply went back to my original code and somehow it spontaneously started working correctly. The following day however, it was back to the original anomalous behavior!
Unable to find a solution to the issue I coded around the problem by saving the worksheet as a comma separated value (.csv) file and using DoCmd.TransferText instead. This strategy circumvented Access' data type guesswork and quickly imported the data into the table. (As an aside, DoCmd.TransferText doesn't like filenames with more than a single period in them.)

Simple VBA/Macro need to create a new text file with the contents of active sheet without changing filename

I need to export data in a sheet to a text file without changing the file name (i.e. not doing "save as". Also it would be great if the file name could look at the previous like file name in the folder and increase by 1 digit (i.e. :file_1.txt, file_2.txt, etc.)...
Thanks!!
If you want to avoid the current name of your excel file being changed, just save the current worksheet, not the whole workbook (the VBA equivalent of the SaveAs function is ActiveWorkbook.SaveAS, to save just the current sheet use ActiveSheet.SaveAS).
You can use the following macro:
Sub Macro1()
Application.DisplayAlerts = False
ActiveSheet.SaveAs Filename:="NewFile.txt", FileFormat:=xlTextWindows
Application.DisplayAlerts = True
End Sub
Toggling the DisplayAlerts property avoids a message box that is displayed if the given file already exists.
If want to save more than one sheet, you need to iterate through the Sheets collection of the ActiveWorkbook object and save each sheet to a separate file.
You can get a new file name as illustrated below, it includes a date. If you would like to add some details on what you want to export, you may get a fuller answer.
Function NewFileName(ExportPath)
Dim fs As Object '' or As FileSytemObject if a reference to
'' Windows Script Host is added, in which case
'' the late binding can be removed.
Dim a As Boolean
Dim i As Integer
Dim NewFileTemp As string
Set fs = CreateObject("Scripting.FileSystemObject")
NewFileTemp = "CSV" & Format(Date(),"yyyymmdd") & ".csv"
a = fs.FileExists(ExportPath & NewFileTemp)
i = 1
Do While a
NewFileTemp = "CSV" & Format(Date(),"yyyymmdd") & "_" & i & ".csv"
a = fs.FileExists(ExportPath & NewFileTemp)
i = i + 1
If i > 9 Then
'' Nine seems enough times per day to be
'' exporting a table
NewFileTemp = ""
MsgBox "Too many attempts"
Exit Do
End If
Loop
NewFileName = NewFileTemp
End Function

Resources