We have .htm files we would like to edit with an Excel macro.
Here's what I have so far, which is an attempt to open the file, replace some placeholders inside the HTML body, and then save the file as an HTML file:
Sub SaveCustomerCountHTML()
Dim customerCountHTML As HTMLDocument
Dim customerCount As String
Dim customerPercentage As String
Dim strHTML As String
Set customerCountHTML = CreateObject("O:\00.Department Documents\06.Status Board Updates\Daily Sales\Templates\CUSTOMER COUNT.htm")
strHTML = customerCountHTML.HTMLbody
customerCount = "55"
customerPercentage = "2"
strHTML = Replace(customerCountHTML.HTMLbody, "%CUSTOMERCOUNT%", customerCount)
strHTML = Replace(customerCountHTML.HTMLbody, "%CUSTOMERPERCENTAGE%", customerPercentage)
customerCountHTML.SaveAs Filename:= _
"O:\00.Department Documents\06.Status Board Updates\Daily Sales\Templates\CUSTOMER COUNT2.htm", _
FileFormat:=xlHtml, _
CreateBackup:=False
End Sub
We definitely don't want to open the file in Internet Explorer - we just want to edit the placeholders in the body and re-save to another folder it without seeing what it's doing.
I receive an error message "ActiveX component can't create object" on the "Set customerCountHTML" line. We were also getting an "Object doesn't support this property or method" error for the HTMLBody lines, even though we included the Microsoft HTML Object Library in our references.
Again, the intention/attempt is to simply open the HTML file as an object, replace text in that file, and save the file. All of this without needing to see anything opening or closing. Most of the answers online include Internet Explorer or Outlook in some way, and we simply want to edit the file.
As #Comintern suggests, HTML files are nothing more than text files. You can open them and work on them as text files, and you can save them as text files, but with an .htm/html extension.
However, working with text files doesn't give you any contextual information, so you can't easily distinguish a table tag, the use of table in css or javascript or attributes, or in actual content.
If you know the exact text you want to replace is unique and reliably found without any False Positives, then replacing the text is good enough. But if you need to be able to find and replace specific parts of the HTML that might be ambiguous, then it might be worth ensuring that the file is XHTML compliant, and opening the file with the MSXML type library. You can then work with the file as an XML Document including a node-tree and all of the MSXML features for finding nodes.
Related
I have a macro which should open, edit and copy the contents of read-only documents into a new document, then closes the original ones without saving. On my computer I get a runtime error 6124: "You are not allowed to edit this selection because it is protected."
When I open the document through VBA it says I am restricted with view only, however when I open it manually I get the notification that the author would like me to open it read only, and I can refuse.
The weird thing is I sent the macro to my colleague to test it, and the same code on the same files can do the editing for them.
Is there a setting I am not aware of that allows this to happen?
Is there a way to get VBA to open the read-only document with editing access?
I have tried to change the document attribute through runtime script, but it did not work:
Dim fso, doc As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set doc = fso.GetFile("path")
doc.Attributes = 0
Documents.Open("path")
End Sub
I found a similar question but it was 5 years 8 months old, had 2 replies and neither worked for me (VB.Net Read txt file from current directory)
My issue is that when I use the following code:
Dim fileReader As String
fileReader = My.Computer.FileSystem.ReadAllText(Application.StartupPath & "\Username_And_Password_Raw.txt")
Dim usernameAndPassword = Split(fileReader, ",")
I get an error saying:
System.IO.FileNotFoundException: 'Could not find file 'C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\bin\Debug\net6.0-windows\Username_And_Password_Raw.txt'.'
I have tried using all the different Applications.BLANKPath options I can find (ie; StartupPath, CommonAppDataPath, etc.) and they all return essentially the same error only with a different location.
This is the folder layout of my TXT File - I know it's a terrible, incredibly insecure and generally awful way of storing login information but this is just for a NEA so will never ever actually be used
This is the actual path of the TXT File if it helps
C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\Username_And_Password_Raw.txt
The startup path is where your exe is located. That and all supporting files get copied to a binary directory when you compile in visual studio, in your case
C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\bin\Debug\net6.0-windows
But what you're trying to do, reference the file where it sits in your solution, is probably not the best way to do it, and your code above will work (with a change, will mention later) if you change the properties of the file in the solution.
Right click on the file in the Solution Explorer Username_And_Password_Raw.txt, select Properties. Modify Copy to Output Directory to either Copy always / Copy if newer, depending on your requirement. Now that file will copy to the same directory your exe is in, and the code above should work.
Note, when creating a path, don't use string concatenation because you may have too many or too few \; use Path.Combine:
Dim filePath = Path.Combine(Application.StartupPath, "Username_And_Password_Raw.txt"
Dim fileContents = My.Computer.FileSystem.ReadAllText(filePath)
I have a Word document that uses VBA forms to generate the document content based on selection boxes. The VBA copies and pastes from other word documents into the main document. I use explicit paths to specify where it should go find the word documents.
It would be nice to use UNC paths instead, to remove some of the "explicitness" of the file locations (c:\Files\Example\Content\PROFILE.docx) and maybe replace it with something like "..\Content\Profile.docx "
Example of the code:
Sub GenerateProfile()
Dim currentPathProfile As String
currentPathProfileText = ActiveDocument.Path
currentPathProfileText = currentPathProfileText & "c:\Files\Example\Content\PROFILE.docx"
Documents.Open FileName:=currentPathProfileText
Dim currentPathProfileDoc As Document
Set currentPathProfileDoc = Documents(1)
currentPathProfileDoc.Activate
Call CopyWholeContent
currentPathProfileDoc.Close
Call PasteWholeContent
End Sub
If the other word documents are in a relative path position to the template holding the code you can do it. It is easier if they are in a subfolder. Generate the path of ThisDocument (your code holder) and use that as a base.
ThisDocument.Path
However, rather than pull from documents, why not have the text stored in your template in the form of AutoText and use that instead? If the information is needed in more than one template, it can be stored in a global template as AutoText. This is much more flexible and less prone to problems, IMO.
I am using the following VB Script in a Word 2010 Doc saved as a Microsoft Word Macro-Enabled Template that is protected for form fields:
Sub SaveWithBkMarkedText()
'This code saves the Word file using the bookmark value for Maintenance Memo.
'The file is also saved to a folder in KnowHow for files related to this template.
Dim FileName As String
FileName = ActiveDocument.Bookmarks("mmn").Range.Text
'Use the C:\ code when saving the file locally
ActiveDocument.SaveAs "C:\Download\TemplatesFolders\" & FileName & ".doc"
MsgBox "Your Draft has been saved to KnowHow's Release Documentation site." & _
&vbCrLf & "The file name uses the MM that you included earlier: " & FileName, _
vbInformation + vbOKOnly, "Draft Saved to Minerva"
End Sub
The value entered into the Form Field for a FORMTEXT legacy-form object uses the Bookmark as the file name. Example, if the user enters 12345 as the value, the file is saved using this value as the filename: 12345.doc. This worked fine until a week ago when the filename is now being Prefixed with FORMTEXT 12345.doc. I have tried using this same VB script in older versions of Word on a different machine, and created from a NEW Template with the script added in from scratch, and the same issue is appearing on that machine as well. Prior to this, I was able to update my template with NO problem, but now I can't update this one FORMTEXT field without it affecting the whole file. I can update any other FORMTEXT in the template that does not use the Bookmark value as the file name, and it works. Also, I have tried changing the Bookmark Reference to another FORMTEXT object, as well as saving the file as a .DOCX and the same problem occurs regardless. What is causing the FORMTEXT to appear in the filename?
You have to un-protect the document (template) and then make the VBA programming. Once it is done, then you can protect it again (for filling forms) and you will not see the "FORMTEXT" in the filename when you run the macro.
Hope it helps.
To the OP, did you resolve this issue? I'm now having the same problem, I'm using form field text with bookmarks and using VB.net to get the bookmark.text which is now prefixed with FORMTEXT, just using a bookmark on it own and its OK, no prefix. I'm going to try and remove the first 9 characters from the result using code, a workaround, yes but it might work.
Know this is an old thread but ran into same issue. As a workaround...
Replace FORMTEXT with null "". In OP circumstance:
Dim FileName As String
FileName = ActiveDocument.Bookmarks("mmn").Range.Text
FileName = Replace(FileName, "FORMTEXT ", "")
Not a "fix" for the issue or elegant but it works.
Had the same issue. Simply delete current bookmark and add a new one. If that does not work than instead of using the following:
FileName = ActiveDocument.Bookmarks("mmn").Range.Text
try using:
Selection.GoTo What:=wdGoToBookmark, Name:="mmn"
Filename = Selection.Text
I have a VBA script used to process Word documents. The first thing the program does is to create an index of the documents in a defined set of folders. It then goes through the list processing each of the indexed documents.
The problem I am having is that it will sometimes decide that a particular document cannot be found, even though it previously indexed the document and a quick spot check shows the document to be in the correct place.
Can anyone shed some light on why VBA should display this behaviour?
The script is using the Dir$ function to index the files, and the Documents.Open function to open each word document for processing.
Sample code:
ChangeFileOpenDirectory (folderName)
inputFileName = Dir$(folderName & "*.doc")
Do While inputFileName <> ""
... call various functions here ...
inputFileName = Dir$
Loop
One of the functions called in the block has the following line:
Set currentDoc = Documents.Open(fileName:=docFileName, AddToRecentFiles:=False, Visible:=False)
This is the point at which the code is failing.
One of the most annoying things I have found is that recent files links are returned as the files themselves with Dir. You can use the FileSystemObject to check the file type.
I copy/paste your code and it works correctly.
However, it leaves all the files open (and hidden), and when you run it in another directory, additional files are opened and added to the open projects (take a look in the VBA editor).
My only guess is that after a while you're hitting the maximum allowable number of open files.
Try adding
currentdoc.Close
just before
inputFileName = Dir$
A few reasons, some duplicated from other answers:
If the path+ filename is long enough ... (you already answered in a comment)
If you are writing new files to same directory, Dir$ may get corrupted (happened to me)
If you have filenames with non-std chars (ex. "#")
Files locked by other processes
Files deleted while the macro is running
You may also try this code ...
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists(file) Then ....
First enable the Microsoft Scripting reference in the VBE