FileSave() Word Macro - vba

I have written a macro which when a file is created and the little save button is clicked the macro is triggered(as it overrides the default FileSave function). The macro extracts information from a table in my document, converts it to a string then cleanses that string of any carriage returns then uses that as the file name. An if statement then runs checking whether a hidden row in the table has a value of 1 and if not then it will set the value to 1 and save the document at the location specified with the new filename.
All of this works great except when I re-open the file to edit it, as my users will do, and click save again it tries to run everything again, completely ignoring my If statements first statement and will add a carriage return to the start of the filename effectively breaking the save function to SharePoint as it has an invalid character in it. If you then click save again it will seemingly run the macro as normal and save it by actually reading the if statement correctly. Am I doing something wrong here?
Here is the code:
Sub FileSave()
Dim strText As String
Dim strClean As String
Dim strFileName As String
Dim strLocation As String
Dim strSavedName As String
Dim strCleanSave As String
strText = ActiveDocument.Tables(1).Rows(1).Cells(2).Range.Text
strClean = Application.CleanString(strText)
strFileName = strClean + "_" + Format(Date, "yyyy-mm-dd")
strLocation = "[My SharePoint Site]"
If ActiveDocument.Tables(1).Rows(1).Cells(3).Range.Text = "1" Then
strSavedName = ActiveDocument.Name
strCleanSave = Application.CleanString(strSavedName)
ActiveDocument.SaveAs FileName:=strSavedName
Exit Sub
Else
ActiveDocument.Tables(1).Rows(1).Cells(3).Range.Text = "1"
ActiveDocument.SaveAs FileName:=strLocation & strFileName & ".docx"
End If
End Sub

Word table cell text ranges are terminated with two hidden chars, a carriage return (ASCII 13) and a bell (ASCII 7). Your IF condition returns false because it is testing the equivalence of "1" and "1" & Chr(13) & Chr(7).
In your case you can limit the test to the first char:
If Left$(ActiveDocument.Tables(1).Rows(1).Cells(3).Range.Text, 1) = "1" Then
More generally you can test the visible cell contents with a Len() - 2.
Hope that helps.

Related

Create/Update footer after SaveAs in Word VBA

I want to generate an automatic footer when I save a new MS Word file, and update the footer if I SaveAs the file.
The code below used to work well with an old Word. With the latest Word it only works if I press F12 on the keyboard. Any help would be greatly appreciated!
Sub FileSaveAs()
Dialogs(wdDialogFileSaveAs).Show
Dim i As Long
Dim ThisPath As String
Dim pName As String
Dim TextInFooter As String
Dim FullName As String
ThisPath = ActiveDocument.Path
pName = ActiveDocument.Name
FullName = ThisPath & "\" & pName
TextInFooter = "This file was saved in: " & FullName & " on the " & Now
For i = 1 To ActiveDocument.Sections.Count
With ActiveDocument.Sections(i)
.Footers(wdHeaderFooterPrimary).Range.Text = TextInFooter
End With
Next
End Sub
As you noticed, the new version triggers the FileSaveAs only on F12. Not sure if this is bug or a feature.
If it is only important that the document shows the information in print or on open - my suggested workaround:
You could avoid the insertion into the footer on save and insert it using fields, the document already has the information you are inserting. You simply need to make it visible. The footer would be then:
This file was saved as { FILENAME \p } the { SAVEDATE \# "dd.MM.yyyy HH:mm:ss"}
Adjust the Date/Time format as needed. You have to force the update of the fields - this is where the auto macros come into it.
Sub AutoOpen()
' set fields to update before printing (if saved as and printed while open)
Options.UpdateFieldsAtPrint = True
' Update all current fields in just opened document
ActiveDocument.Fields.Update
End Sub
Sub AutoClose()
' update fields when closing
ActiveDocument.Fields.Update
End Sub
The only difference would be, that you have the full path including file name and extension there. Additionally, there might be times, when the file is saved but not yet opened/closed/printed and has also not updated the fields.
In theory, you could insert the footer into the document with the AutoOpen macro as well (activedocument.fields.add).

Open file explorer and search for variable in textbox

I the user to enter a keyword in a text box and when the macro is executed;
Open a new Windows' File Explorer window designated by a path.
path = C:\Users\ME\Desktop\Folder7
Search from the variable in SearchBox1 (this is a ActiveX text box on a worksheet.)
mySearch = sht.OLEObjects("SearchBox1").Object.Text & "*"
I saw multiple posts using Shell commands to open a File Explorer Window.
Call Shell("explorer.exe " & Chr(34) & "search-ms:query=*.pdf&crumb=location:C:\Users\ME\Desktop\Folder7" & Chr(34), vbNormalFocus)
When I run the above line there is an error from the explorer.
'Windows cannot find ". Make sure you typed the name correctly, and then try again.'
I need the macro to search for all files associated with the string. Folder names, file names, and words/characters within each type of document. They have all been OCR'd and Indexed by Windows.
It should have the ability to search for incomplete words as well.
I got Shell to open an explorer window to the path by
Call Shell("explorer.exe " & Chr(34) & "C:\Users\ME\Desktop\Folder7" & Chr(34), vbNormalFocus)
How can I search all folders and sub-folders within this freshly opened window?
I don't need the results compiled into Excel or any other program. I just need to make a quick search button as if you were to manually open this folder and use the search bar.
This worked for me:
Sub Tester()
ShowSearch "C:\_Stuff\test", "*.pdf" 'search by file name
ShowSearch "C:\_Stuff\Mail\", "reminder", True 'search by keyword
End Sub
Sub ShowSearch(searchWhere, searchFor, Optional SearchByKeyword As Boolean = False)
Const CMD As String = "explorer.exe ""search-ms:crumb=name:{query}&crumb=location:{location}"" "
Dim s
s = Replace(CMD, "{query}", WorksheetFunction.EncodeURL(searchFor))
s = Replace(s, "{location}", WorksheetFunction.EncodeURL(searchWhere))
If SearchByKeyword Then s = Replace(s, "crumb=name:", "crumb=")
'Debug.Print s
Shell s
End Sub
Note: WorksheetFunction.EncodeURL() is 2013 and later. For alternatives see:
How can I URL encode a string in Excel VBA?
Double Click on Cell to search
This is a solution I have combined from various places to open an explorer window at a path, that are filtered (searched) by the term in the selected cell using the windows File Explorer search function. It is triggered by a double click on a cell that contains the search term:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Application.Intersect(Target, Range("A1:AA1048576")) Is Nothing Then
Dim d As String
Dim searchpath As String
Dim searchlocation As String
Cancel = True
d = Selection.Value
'change window name to make sure new explorer window is opened for each instance
'copy string from manual search
searchpath = "search-ms:displayname=" & d & "%20Results%20&crumb=System.Generic.String%3A"
'copy string from manual search (e.g. my documents replace USERNAME)
searchlocation = "&crumb=location:C%3A%5CUsers%5CUSERNAME%5CDocuments"
If Not d = "" Then
Call Shell("explorer.exe """ & searchpath & d & searchlocation & "", 1)
'src: https://stackoverflow.com/questions/24376850/open-explorer-search-from-excel-hyperlink
End If
End If
End Sub
This opens the window in VbNormalFocus, with the window title set to the cell variable (d). The ensures that if this code is run on another cell value a new separate window will be opened. Without this I found the next time I ran the code the explorer window was not updated with the new search value, but just changed focus to the previous result.
edit: "copy from search bar" is the string after location: in the address bar of a manual search in explorer
Using ActiveX Controls
Add an ActiveX Text box (TextBox1) and button (CommandButton1) and add the following codeto the command button:
Private Sub CommandButton1_Click()
Dim d As String
Dim searchpath As String
Dim searchlocation As String
Cancel = True
d = TextBox1.Value
'change window name to make sure new explorer window is opened for each instance
'copy string from manual search
searchpath = "search-ms:displayname=" & d & "%20Results%20&crumb=System.Generic.String%3A"
'copy string from manual search (e.g. my documents replace USERNAME)
searchlocation = "&crumb=location:C%3A%5CUsers%5CUSERNAME%5CDocuments"
If Not d = "" Then
Call Shell("explorer.exe """ & searchpath & d & searchlocation & "", 1)
'src: https://stackoverflow.com/questions/24376850/open-explorer-search-from-excel-hyperlink
End If
End Sub
Now the user can change the text in the text box and clicking the button will open a windows file explorer search of the designated folder in the code.
Screenshot example using button search for "Editable Search Text"
EDIT
You can include additional search functions with the Windows search syntax:
http://download.microsoft.com/download/8/1/7/8174a74e-3d8d-4478-abc6-84cd51ad93c4/Windows_Desktop_Advanced_Query_Reference.pdf
Eg. you can search within the folder for all files with a partial match of each word in the string by changing the search variable "d:
...
d = Selection.Value
d = "(" & Replace(d, " ", " OR ") & ")"
...
if the selection (d) had a value of Where will I find it
This will search for (Where OR will OR I OR find OR it) in windows explorer and would return files with names such as WHEREver and Last WILL and testament. I've found this useful for qualitative information, where casting a wider search is acceptable and can be easily filtered through by the user (NOTE: the above example would also return all files with a name containing i so it is not very specific!)
executing Dir() empty after a Dir() with a given path will start to list all files in that dir, you just use if InStr() <> 0 to check against your value.
sFileName = Dir(path)
Do While sFileName > ""
tmp = tmp & sFileName & ";" : sFileName = Dir()
Loop
List() = Split(tmp, ";")
there you have a list of all files inside that path, you can check sub folders the same way by going through each one doing the same thing.
I do not take credit for the idea, it's awesome that you can do this. I just took the idea a step further and made it modular, so you can add any type of search:
Sub searchInExplorer_TEST()
'searchInExplorer "D:\", , , True, "*.jpg", True, "24 Feb 20"
searchInExplorer "D:\", , , , , True, "24 Feb 20", True, "picture"
End Sub
Sub searchInExplorer(searchWhere _
, Optional isSearchAll As Boolean, Optional strAll _
, Optional isSearchName As Boolean, Optional strName _
, Optional isSearchModified As Boolean, Optional strModified _
, Optional isSearchType As Boolean, Optional strType)
'*****************************************************
'https://stackoverflow.com/questions/52671500/vba-to-open-file-explorer-and-search-for-variable-in-textbox
'ALLOWS SEARCHING IN WINDOWS EXPLORER USING VARIABLES
'EITHER USE SEARCH ALL OR OTHER SEARCH TIMES
'EACH SEARCH TYPE HAS AN ON/OFF SWITCH AND A STRING VARIABLE TO SEARCH BY
'*****************************************************
Dim STR As String
STR = "explorer.exe ""search-ms:"
If isSearchAll Then
STR = STR & "crumb=:" & WorksheetFunction.EncodeURL(strAll)
Else
If isSearchName Then
STR = STR & "&crumb=name:" & WorksheetFunction.EncodeURL(strName)
End If
If isSearchModified Then
STR = STR & "&crumb=modified:" & WorksheetFunction.EncodeURL(strModified)
End If
If isSearchType Then
STR = STR & "&crumb=kind:" & WorksheetFunction.EncodeURL(strType)
End If
End If
STR = STR & "&crumb=location:" & WorksheetFunction.EncodeURL(searchWhere)
STR = STR & """ "
Debug.Print STR
Shell STR
End Sub

VBA saving Excel to Sharepoint freezes forever with a screen showing “Getting list of available content types and properties…”

I have VBA that, along with a whole lot of other stuff, saves an excel workbook to SharePoint (enterprise 2010 I think) and it works fine most of the time but every once in while, when a user runs the VBA, the Excel freezes with a pop up showing "Getting list of available content types and properties...". If the user selects cancel another pop up come up "Run-time error '1004': Method 'SaveAs' of object '_Workbook' failed. If the user selects 'Debug' the last line of VBA is highlighted as creating the error.
Dim fileName As String
Dim excelDirName As String
fileName = [c9]
excelDirName = [c16] & "/"
ThisWorkbook.SaveAs excelDirName & fileName & ".xls"
Since this works sometimes (and it worked for over 6 months without this happening) and not other times I am not sure what it could be and I am thinking something was updated in SharePoint.
I would write it a bit differently, so as to make it more robust:
With SomeSpecificSheet
Dim path As String
path = .Range("SavePath").Value
Dim fileName As String
fileName = .Range("SaveFileName").Value
End With
Debug.Assert Trim(path) <> vbNullString
Debug.Assert Trim(fileName) <> vbNullString
Dim savePath As String
savePath = path & "/" & fileName
ThisWorkbook.SaveAs savePath
Note:
Be explicit about the worksheet you're reading from - you're currently reading from whatever the active sheet is, and unless every single worksheet in ThisWorkbook has the expected values in $C$9 and $C$16, that's asking for trouble.
Use named ranges, so that if a user inserts a column before column C or a row before row 9, your code still refers to the correct cells.
Let SaveAs determine the file's extension.
Use Debug.Assert to verify assumptions (and break before you freeze). Alternatively, you can explicitly validate the values, for example:
If path = vbNullString Or fileName = vbNullString Then
MsgBox "I need a path!"
Exit Sub
End If

Excel VBA: Make InStr find whole string, not part of it

I'm trying to make a login/register system.
This is the registration UserForm.
Private Sub regReg_Click()
Dim TextFile As Integer
Dim FilePath As String
If regAParole.Text = "aparole" Then
FilePath = ThisWorkbook.Path & "\accounts.txt"
TextFile = FreeFile
Open FilePath For Append As #1
Print #TextFile, regID; regAmats; regParole
Close TextFile
MsgBox ("Registracija veiksmiga.")
Unload Registracija
Else
MsgBox ("Nepareiza administratora parole.")
End If
End Sub
The "aparole" thing is basically just a keyword to enter in a field so only administrators can create new accounts.
accounts.txt content looks like:
1DirectorPassword (ID+jobposition+password)
This is the authentication:
Private Sub logAuth_Click()
Dim TextFile As Integer
Dim FilePath As String
Dim FileContent As String
Dim find As String
Dim result As Integer
find = logID & logAmats & logParole
FilePath = ThisWorkbook.Path & "\accounts.txt"
TextFile = FreeFile
Open FilePath For Input As TextFile
FileContent = Input(LOF(TextFile), TextFile)
result = InStr(FileContent, find)
If result >= 1 Then
MsgBox ("Autorizacija veiksmiga!") ' Success
Unload Autorizacija
End If
Basically when logging in I search within the accounts.txt for the string combo (ID+jobposition+password) which I use when registering. So in general the approach works, but:
If I enter everything perfectly matched = works great
If I enter the password half of it, like in a format of = 1DirectorPass it still works, so basically how can I tell to only search for the whole string and not parts of it?
I think the issue lies within InStr...
You could test for the newline markers in your file content, like this:
result = InStr(vbCrLf & FileContent, vbCrLf & find & vbCrLf)
This will only match complete lines. An extra newline is added before the file content so also the first line can be matched. At the end of the file content you would already have a vbCrLf character, because Print is supposed to add that.

Outlook VBA macro to create txt file

I am not very clued up with VBA and need some help with the following:
I want to create a txt file and save it in a specific location (overwriting the existing file with the same name).
The text file must countain the last word in the email subject, which will be an Account Number. For the purpose of this explanation I'm going to call the account number Variable1.
if the Email Subject = Account Recon - 10201314050019434586
then Variable1 = 10201314050019434586
The text file that must be created/replaced:
C:\Users\tenba1\Documents\QlikView\Account Recons\Recon_Acct.txt
The text in the file must be:
SET vAcct = 'Variable1';
So in this example the text in the file must be:
SET vAcct = '10201314050019434586';
The macro must look at the last word in the subject (i.e. everything after the last space) - an account number is not always 20 digits.
Thanks in advance
This should do the trick. It's a macro script which takes the Subject of the top opened email and writes the Accountnumber into Recon_Acct.txt. If there is no number, the text will be SET vAcct = ''. The File will be overwritten, every time you execute the script.
Sub writeSubjectToFile()
Const FILEPATH = "C:\Users\tenba1\Documents\QlikView\Account Recons\Recon_Acct.txt"
Dim objEmailItem As Object, strSubject
Dim strSubject As String
Dim strText As String
Set objEmailItem = Application.ActiveInspector.CurrentItem
strSubject = objEmailItem.subject
strText = Trim(Right(strSubject, Len(strSubject) - InStr(1, strSubject, "-")))
Open FILEPATH For Output As 1
Print #1, "SET vAcct = '" & strText & "';"
Close #1
End Sub