Months ago I wrote a small Makro for my Company and until now it worked just fine.
Recently (maybe because we updated Office Version) there is a bug, that excel adds a new line in a print statement.
Code:
outputString = value1 & " " & value2 & " " & value3 & " " & value4 & " " & value5 & " " & user & " " & date
used to give me this output:
22 S ***/***s 9932256 B*****t Fatma 811 R******r Alexander 27.12.2019
now gives me this output:
22 S ***/***s 9932256 B*****t Fatma 811 R******r Alexander
27.12.2019
As you can see, excel adds a newline.
Can somebody tell me what happends here?
EDIT:
Solution:
Excel adds the new line after using:
user = Application.UserName
Maybe this is due to the office update we had. So I just took substring and cut the last character and works fine now.
Application.Username returns as the documentation states the username. As it is Read/write it can indeed happen that you will get a username that contains a vbLf or vbCrLf. Have a look at the following example
Sub UserName_VbCrlf()
Dim origUser As String
Dim user As String
' Be careful when testing as it replaces your username!!
' Maybe you save it first
origUser = Application.UserName
Application.UserName = "Storax" & vbLf & "Home adress"
user = Application.UserName
' This will give different lengths
Debug.Print Len(user), Len(Replace(user, vbLf, ""))
' Restore original username
Application.UserName = origUser
End Sub
Related
I have a column whose cells have comments via CommentsThreaded and CommentThreaded objects. In another column, I successfully copy the contents of these threads using the function =GetComments(A1), as shown below:
' Returns the concatenated string of parent and child comments for the specified input cell.
Function GetComments(SelectedCell As Range) As String
Set CellComment = SelectedCell.CommentThreaded
Dim Result As String
If Not CellComment Is Nothing Then
Result = CellComment.Author.Name & ": """ & CellComment.Text & """ " & vbNewLine & vbNewLine
Dim ChildCount As Integer
ChildCount = 1
For Each ChildComment In CellComment.Replies
Result = Result & "[Reply #" & ChildCount & "] " & ChildComment.Author.Name & ": """ & ChildComment.Text & """ " & vbNewLine & vbNewLine
ChildCount = ChildCount + 1
Next
Else
Result = "No Comments"
End If
GetComments = Result
End Function
Example output would be: John Doe: "My comment"
However, I've noticed that when a comment is added/edited/deleted, the output cell that uses the GetComments function is not updated. I have to manually re-run the function in the output cell to get its contents to update by selecting it and pressing Enter.
I've tried using all of the typical event handlers, such as Worksheet.Change, SelectionChange, etc. None of the events fire when a comment is modified. Neither does manually forcing Volatile or Calculate. It's almost like the Add/Delete/Edit methods of CommentsThreaded are not included in workbook events at all.
Is this possible? Thanks!
Ok , here is the thing,
I have created a next invoice number program in which by pressing of a macro assigned button active invoice automatically saved and closed and the next invoice with a number increased appear.My problem is that, I want excel invoices to be created in their relevant folder by their first two digits of invoice number . as an example : 04-001 where 04 stands for April. also, when invoice number is given 05-002, the directory folder of may 2018-19 should be auto created and invoice should be there in the folder only. i am trying to figure out the code since some time but no luck till now. So far , The invoices are created according to date only but as darren said it is a problem for me when i am trying to create invoices from december on first day of january.
This is my current code :
Sub SaveInvoiceM()
Dim NewFN As Variant
If Len(Dir("C:\Invoices\" & Format(Date, "MMM YYYY") & "-" & (Format(Date, "YY") + 1), vbDirectory)) = 0 Then
MkDir "C:\Invoices\" & Format(Date, "MMM YYYY") & "-" & (Format(Date, "YY") + 1)
End If
' Copy Invoice to a New Workbook
NewFN = "C:\Invoices\" & Format(Date, "MMM YYYY") & "-" & (Format(Date, "YY") + 1) & "\Inv" & Range("F5") & ".xlsx"
ActiveWorkbook.saveas NewFN, FileFormat:=xlOpenXMLWorkbook
NextInvoice
End Sub
Range("F5") stands for my invoice number which is 04-001
I see what you are trying to do (keep nicely organized, automatically) and that's an excellent goal.
I have a suggestion of an alternate invoice numbering system (based on what I'm understanding of your situation & experience level) that will make tasks (like this "auto-filing" process) much easier, and will also simplify the process any time you (or especially anyone else) needs to look back at these invoices. There are a number of obvious benefits (same idea as metric vs imperial).
Ideal numbering system: (in my opinion)
To reduce confusion: Give each invoice and filename the same name instead of having a filename with a month and
Since you want granularity from months to years (but not days): make the invoice/file name include the all of those fields.
To make sorting & finding these logical (easier): place each "date part" in order of biggest to smallest. A unique sequential number goes at the very end.
Your code sample was a good start - I just have a bit of OCD when it comes to this kind of thing, and creation of a numbering system is an important task. (Also this will be "date-proof", and error-checked along the way...
This is a little different than what you had because instead of you telling the code what the next invoice number is, it tells you (by figuring out the next number in sequence based on the existing files).
Like yours, it creates a folder if necessary. Since the files are number YYMM-nnn then are always in the correct order when you sort them. (The "month folders" are unnecessary since the month is in the filename, but I included them anyway since that was your plan. You could just keep every month's invoices in one folder, and they'd still be organized in order of month.)
VBA #1: Save file with next sequential invoice number (creating folder if necessary)
Sub createInvoiceNumberAndSave()
'creates a new invoice number based on date in specified cell & creates new folder if necessary
'finds next unused invoice number & verifies that file is properly saved
Const invoicePath = "c:\invoices\" ' invoice root save path
Const fNamePrefix = "Inv" ' prefix for the filename
Const fNameExt = ".xlsm" ' file extension
Const getInvoiceDate = "F5" ' we GET the DATE of the invoice from F5
Const putInvoiceNumber = "F6" ' we will PUT the new filename into cell F6
Dim invDate As Date, folderName As String, fName As String, fNum As Long, nextInvoiceNum As Long
'get the invoice date and make sure it's valid
If IsDate(Range(getInvoiceDate).Value) Then
'valid date found in cell F5
invDate = Range(getInvoiceDate).Value
Else
'valid date not found in F5. Do we want to default to today's date?
If MsgBox("Cell " & getInvoiceDate & " does not contain a valid date." & vbLf & vbLf & _
"Do you want to use today's date instead?", vbQuestion + vbOKCancel, "Date not found") <> vbOK Then
Call MsgBox("Invoice Not Saved.", vbCritical + vbononly, "User Cancelled")
Exit Sub 'stop running
Else
invDate = Date 'use today's date
End If
End If
'find the next unused invoice number for this month
folderName = Format(invDate, "YYMM")
nextInvoiceNum = 0
'figure out the next unused "file number"
fName = Dir(invoicePath & folderName & "\" & fNamePrefix & folderName & "-*" & fNameExt)
If fName = "" Then
'file not found
If Dir(invoicePath & folderName, vbDirectory) = "" Then
'month not found - create folder?
If MsgBox("Okay to create folder '" & invoicePath & folderName & "' for invoice #" & folderName & "-001 ?", _
vbOKCancel + vbQuestion, "Folder not Found") <> vbOK Then Exit Sub
'create folder
MkDir (invoicePath & folderName)
End If
Else
'month found. Now find the highest invoice number in the folder.
Do While fName <> ""
Debug.Print "Found File: " & fName
'get the number (filename = fNamePrefix & "YYMM-___.xlsx" so we know where it is
If IsNumeric(Mid(fName, 6 + Len(fNamePrefix), 3)) Then 'it's a valid number
fNum = Val(Mid(fName, 6 + Len(fNamePrefix), 3))
'if it's the biggest so far, remember it
If fNum > nextInvoiceNum Then nextInvoiceNum = fNum 'biggest one so far
End If
fName = Dir
Loop
End If
'we have the next available invoice#
nextInvoiceNum = nextInvoiceNum + 1 'new invoice# (numeric)
'PUT the new invoice# (text) in cell F6
Range(putInvoiceNumber).Value = fNamePrefix & folderName & "-" & Format(nextInvoiceNum, "000")
fName = invoicePath & folderName & "\" & Range(putInvoiceNumber).Value & fNameExt
Debug.Print "Saving as: " & fName
'save file
ActiveWorkbook.SaveAs fName
'DOUBLE CHECK check that file exists (couple lines of code now save a headache later)
If Dir(fName) = "" Then
'something went wrong (file wasn't saved)
Call MsgBox("ERROR! FILE NOT SAVED: " & fName, vbCritical + vbOKOnly, "ERROR!")
Stop
End If
'success message!
Call MsgBox("Invoice saved successfully:" & vbLf & vbLf & fName, vbInformation, "Invoice Created")
'NextInvoice '?
End Sub
EDIT: ("Back to your way")
I can think of a number of ways that your method will be a problem, some of which I tried explaining, but you're determined to number & organize these files your way, so "here you go".
VBA #2: Save file with cell value as name:
This procedure saves the current file, named from the invoice number (like 04-001) that you enter in cell F5 (creating folder if necessary):
Sub SaveFileBasedOnInvoiceNumber()
Dim monthNum As Long, yearString As String, folderName As String, fName As String
'build filename
On Error Resume Next 'skip errors for now
monthNum = Val(Left(Range("F5"), 2))
yearString = Year(Date) & "-" & Right(Year(Date) + 1, 2)
folderName = "c:\invoices\" & StrConv(monthName(monthNum, True), vbUpperCase) & " " & yearString
fName = folderName & "\INV" & Range("F5") & ".xlsm"
'check if there was a problem
If Err Then MsgBox "Invalid invoice number": Exit Sub
MkDir (folderName) 'create folder
On Error GoTo 0 'turn error checking back on
'Confirm file saved properly
ActiveWorkbook.SaveAs fName 'save file
If Dir(fName) = "" Then MsgBox "Error! File not saved: " & fName: Exit Sub
MsgBox "Invoice saved successfully:" & vbLf & fName
End Sub
I'll leave "VBA #1" in the the top of the answer for others seeking a logical numbering & storage system with auto-generated invoice numbers.
(One day you'll figure out why that way would've been better, but be forewarned, it will be a lot more of a hassle to change your organization method later!)
Good luck!
Can you explain why this code does not include a $ when saving as a file name?
Sheets("Input").Range("F18").Value & " - $" & Sheets("Input").Range("M13").Value
When I run the file to pdf it simply disregards the $. How can I change the cell value M13 to be formatted as a dollar amount, preferably including "," when at or over $1,000
Thanks!
You can't include a , in your file name! So you can't carry that format in to the filename in any way. However, if your just talking about the cell when looking on the sheet, right click and format it that way in the options
As for the "$" not showing, try this:
Dim FName as string
Fname = Sheets("Input").Range("F18").Value & " - $" & Sheets("Input").Range("M13").Value
Works fine when tested.
Update
Tested again with this:
Sub test()
Dim N1 As Double
N1 = Sheets("Sheet1").Range("B3")
ActiveWorkbook.SaveAs ("Test - $" & N1)
End Sub
where N1 = 1000 formated as $X,XXX.xx (where x is a number obviously) and works fine. The output I got was a file name called: Test - $1000.xls
Sub testSave()
Dim SaveToDirectory As String
'just checking string looks good comment or delete when happy
MsgBox ("other text you want " & Cells(18, 6).Value * 100 & "%-" & Format(Cells(13, 13).Value, "Currency"))
'set save directory
SaveToDirectory = "C:\Users\DMASON2\Documents\"
'set file name
ActiveWorkbook.SaveAs Filename:=SaveToDirectory & "FileName-" & Cells(18, 6).Value * 100 & "%-" & Format(Cells(13, 13).Value, "Currency"), FileFormat:=xlWorkbookDefault
End Sub
I have a function which sets a variable for the current user. The variable name is prefixed with the name of the module - basically, the way the application is set up, Client is a class, Server is a class, Agency is a class and so on. This is an attempt to create a system whereby we can find out any key information about a client or one of their websites, across over 200 servers, with as few clicks as possible and using live data from their DB.
The function is as follows:
public sub setVariable(varName, varValue)
varValue = cstr(varValue)
def = ""
if varValue = "" then def = "1"
response.write vbcrlf & "Variable: " & varName & " : " & varValue & vbcrlf
if not cstr("" & getVariable(varName, def)) = cstr("" & varValue) then
response.write vbcrlf & varName & " : " & varValue & vbcrlf
prepend varName, "Module." & Name & "."
response.write vbcrlf & varName & " : " & varValue & vbcrlf
session(varName) = varValue
Core.RunSproc "SetUserVariable", array("#name", "#value"), array(varName, cstr(varValue)), setVar
end if
end sub
Now on line 5, where it is first output, only "ID" is output as the variable name. However 2 lines later the name is set to "Module.<module-name>.ID" (for example Module.Server.ID. 2 lines after that, after the prepend statement (which acts the same as doing varName = "something" & varName), it outputs the something + "Module.<module-name>.ID". In effect, in this case, it outputs "Module.Server.Module.Server.ID". Note that if I take anything out, it is taken out of the first Module.Server but not the 2nd. Does anyone have any idea what is causing this? It seems as though Module.Server is being prepended to the variable name between lines 5 & 7, but the only line there is an if statement. Thanks in advance.
Seems I have found the answer. It's the fact that ASP automatically assumes variables input into functions are byref. Thus, when calling getVariable, I was actually prepending "Module.Server." there too, and because it was byref the variable maintained the value.
Regards,
Clarkey
Hey guys I'm trying to set the name of a data series to something that contains Unicode characters, and I'm having a hell of a time. For instance, I want the series name to be this:
ε = n²-k²
I've looked at a handful of posts, but none (that I saw) had a similar situation. The fact that I'm new to Excel VBA scripts means that I have probably overlooked something simple. I know that the specific chart exists, because this bit of code is just something I've used before that worked with the addition of a few extra bits here and there. I keep getting the error "Runtime error (1004): Application defined or object-defined error." Here is what I have at the moment:
ActiveSheet.ChartObjects(1).Activate
Dim chart1 As String
chart1 = "= " & ChrW(&H3B5) & " = n" & ChrW(&HB2) & " - k" & ChrW(&HB2) & " 6-5-2012"
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(1).Name = chart1
ActiveChart.SeriesCollection(1).XValues = ActiveSheet.Range("F2:F602")
ActiveChart.SeriesCollection(1).Values = ActiveSheet.Range("N2:N602")
The debugger says that the following line is the cause of the error:
ActiveChart.SeriesCollection(1).Name = chart1
Is this what you are trying?
chart1 = ChrW(&H3B5) & " = n" & ChrW(&HB2) & " - k" & ChrW(&HB2) & " 6-5-2012"
You are getting that error because it is referring to it as a formula since it starts with an "=" sign
If you want to show the "=" sign then include a space before it. For example
chart1 = " = " & ChrW(&H3B5) & " = n" & ChrW(&HB2) & " - k" & _
ChrW(&HB2) & " 6-5-2012"
SNAPSHOT
A snapshot of both methods.