Passing MS-Access string >255 characters to MS-Word field - ms-access

I'm using .FormFields("WordBookmarkName").Result = stringFromAccess method to pass data out of MS-Access to an MS-Word document.
It seems it can only pass up to 255 characters. Is there a way I can pass more to my field in MS-Word?
Edit:
This is a simplified version of the code I was using that works ok up to 255 characters:
Dim startForms As String
Dim appWord As Word.Application
Dim doc As Word.Document
startForms = String(256, "x")
Set appWord = GetObject(, "Word.Application") 'Set appWord object variable to running instance of Word.
If Err.Number <> 0 Then
Set appWord = New Word.Application 'If Word isn't open, create a new instance of Word.
End If
Set doc = appWord.Documents.Open("C:\myFolder\MyForm.docx", , True)
With doc
.FormFields("wdStartForms").Result = "" 'Clear anything currently in the form's field
.FormFields("wdStartForms").Result = startForms
.Visible = True
.Activate
End With
Set doc = Nothing
Set appWord = Nothing
JohnnyBones: this is the code I adapted after your answer; using ActiveDocument wasn't working, so I continued to use the doc reference I'd made and it seemed to work ok with 256+ characters after that:
Dim startForms As String
Dim appWord As Word.Application
Dim doc As Word.Document
startForms = String(256, "x")
Set appWord = GetObject(, "Word.Application") 'Set appWord object variable to running instance of Word.
If Err.Number <> 0 Then
Set appWord = New Word.Application 'If Word isn't open, create a new instance of Word.
End If
Set doc = appWord.Documents.Open("C:\myFolder\MyForm.docx", , True)
With doc
.FormFields("wdStartForms").Result = "" 'Clear anything currently in the form's field
.Bookmarks("wdStartForms").Range.Fields(1).Result.Text = startForms
.Visible = True
.Activate
End With
Set doc = Nothing
Set appWord = Nothing

If you use:
Dim FmFld As FormField, Str1 As String
Str1 = (a long string > 256 characters)
Set FmFld = ActiveDocument.FormFields(1)
FmFld.Result = Str1
You get an error: “String too long” (a ridiculous “design” feature, given that you can do it manually without problems!).
Same if you use:
ActiveDocument.Formfields("Text1").Result = Str1
You can get round this by using:
ActiveDocument.Unprotect
FmFld.Range.Fields(1).Result.Text = Str1
ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True
Or if you're referring to the formfield by name:
ActiveDocument.Unprotect
ActiveDocument.Bookmarks("Text1").Range.Fields(1).Result.Text = Str1
ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True
You could also try passing multiple strings and concatenating them, chopping each string into chunks less than 255 characters.

Related

If-Then-Else Opening Word Document

I'm trying to create an If-Then-Else statement in MS Access VBA.
This statement is to open a specific word document but if the word document does not exist then open a different word document.
Below is the code I have and it works if I get rid of the else but that doesn't solve my problem because I need the else statement.
Dim appword As Word.Application
Dim doc As Word.Document
Dim Path As String
Set appWord = GetObject(, "word.application")
If Err.Number <> 0 Then
Set appWord = New Word.Application
appWord.Visible = True
End If
If Value = "Excused" Then
Path = "C:\...existing docx"
Else
Path = "C:\...different docx"
End If
Set doc = appWord.Documents.Open(Path, , True)
Use appword.Documents.Add to return a new Document. You should also add an Error Handler when using GetObject. You may also consider using Len(Dir(Path)) to test if the file exists.
Dim appword As Word.Application
Dim doc As Word.Document
Dim Path As String
On Error Resume Next
Set appword = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set appword = New Word.Application
appword.Visible = True
End If
On Error GoTo 0
If Value = "Excused" Then
Path = "C:\...existing docx"
Set doc = appword.Documents.Open(Path, , True)
Else
Set doc = appword.Documents.Add
End If
Validate the document exists and if not add a new document.
Sub T()
Dim appword As Word.Application
Dim doc As Word.Document
Dim Path As String
Set appword = New Word.Application
appword.Visible = True
If Len(Dir("C:\...existing docx")) > 0 And Value = "Excused" Then
Path = "C:\...existing docx"
Set doc = appword.Documents.Open(Path, , True)
Else
Set doc = appword.Documents.Add
End If
End Sub

Microsoft access vba-shift focus from access to word

I am creating and opening a word document through access 2007 vba. The document is created but the focus is not shifted to word. Instead the focus still remains on access form through which am creating the doc. Below is my code:
Dim obj As Word.Application
Dim wor As Word.Document
Dim str As String
str = "C:\hello\folder1\vin.dot"
Set obj = CreateObject("Word.Application")
Set wor = obj.Documents.Add
With wor
.SaveAs str
.Close
End With
obj.Visible = True
obj.Documents.Open str
obj.WindowState = wdWindowStateMaximize
Any sugesstions please.
You can move the focus with AppActivate;
AppActivate "Microsoft Word"
The VBA Word.Application object may have more than one Window associated with it. You may specify which Window to display by using its Caption property.
Since you created a new Word.Application and only created one Document, you may assume that the 1st element (1-based array) is what you want to display in your code.
AppActivate (obj.Windows(1).Caption)
I was able to call the specific window even with other word documents open with the following:
Private Sub but_Click()
'must add tools > references Microsoft Word XX.X Object Library (xx.x is max update)
Dim WordApp As Word.Application
Dim WordDoc As Word.Document
strProjPath = Application.CurrentProject.Path 'get current path
strVerWord = "test" 'i use this to identify paths that can change based on network configs.
posOp = InStr(1, strProjPath, strVerWord) ' find the verification word in the path
strVerPath = "strVerWord filepath\FP\FP\document.docx" 'create string location for document
strPathPlusDBName = Left(strProjPath, posOp - 1) & strVerPath
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = True
Set WordDoc = WordApp.Documents.Open(FileName:=strPathPlusDBName, ReadOnly:=True) 'open word file in read only
AppActivate WordDoc
End Sub

Read file using MS Access

I am working on ms access 2013 but found some error. I'm trying to read data from text file but it show error. I search everywhere but not replicate the problem. Please help me to resolve this problem.
Code
Set fs = Application.FileSearch 'Get Error on this line
With fs
Debug.Print CABPath
.LookIn = CABPath
.SearchSubFolders = True
.FileName = ConFileNm
If .Execute() > 0 Then
For FileNum = 1 To .FoundFiles.Count
Next
End If
End With
Error Description
Run-time error 2455:
You entered an expression that has an invalid reference to the property FileSearch
Application.FileSearch, has been discontinued since 2007 versions. So it would not be available to use on 2013. You have some alternatives like Scripting.FileSystem object. There is some explanation and alternatives in this site : http://www.mrexcel.com/forum/excel-questions/268046-application-filesearch-gone-excel-2007-alternatives.html
Hope this helps ! Good luck.
There are also multiple workarounds for this to be found through google;
Function GetFiles(MatchString As String, StartDirectory As String, Optional DrillSubfolders As Boolean = False) As Variant
Dim Results() As Variant
ReDim Results(0 To 0) As Variant
CheckFiles Results, MatchString, StartDirectory, DrillSubfolders
If UBound(Results) > 0 Then
GetFiles = Results
Else
GetFiles = ""
End If
End Function
Sub CheckFiles(ByRef Results As Variant, MatchString As String, StartDir As String, Drill As Boolean)
Dim fso As Object
Dim fld As Object
Dim sf As Object
Dim fil As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set fld = fso.GetFolder(StartDir)
For Each fil In fld.Files
If LCase(fil.Name) Like LCase(MatchString) Then
If LBound(Results) > 0 Then
ReDim Preserve Results(1 To UBound(Results) + 1)
Else
ReDim Results(1 To 1)
End If
Results(UBound(Results)) = fil.Name
End If
Next
If Drill Then
For Each sf In fld.SubFolders
CheckFiles Results, MatchString, sf.Path, Drill
Next
End If
Set fil = Nothing
Set sf = Nothing
Set fld = Nothing
Set fso = Nothing
End Sub
You would call this in your form through something like this;
Dim FileList As Variant
Dim Counter As Long
FileList = GetFiles("*.jpeg", "c:\folder\subfolder", True)
' to NOT look in subfoldres:
'FileList = GetFiles("*.jpeg", "c:\folder\subfolder", True)
If IsArray(FileList) Then
With DoCmd
.SetWarnings False
For Counter = LBound(FileList) To UBound(FileList)
.RunSQL "INSERT INTO [mytable] (FilePath) VALUES ('" & _
FileList(Counter) & "')"
Next
.SetWarnings True
End With
End If
NOTE: Code found through google: http://www.experts-exchange.com/Database/MS_Access/Q_28027899.html

VBA ActiveDocument Concerns / Alternatives?

I'm using VBA in access to open up a protected word template, fill in the data, and then re-protect it.... this way, if the database system goes down, the word template can still be used manually in its protected state.
I have just started using VBA and in this line:
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
I'm concerned that whilst running the code in access, that if the user opens up another word document and makes it the focus, that it will occidentally get protected instead of the other. How do I keep active focus on the document I'm writing to... or do I need to reference my document somehow using WordApp.protect (or something similar that works)
Private Sub Command0_Click()
Dim WordApp As Word.Application
Dim strDatabasePath As String
Dim strTemplatePath As String
Dim strTemplate As String
Dim strJobTitle As String
Dim strFile As String
strFile1 = "testcoc.dotx"
strFile2 = "testcoc-private.dotx"
strDatabasePath = CurrentProject.Path & "\"
strTemplatePath = "\templates\"
strTemplate = strDatabasePath & strTemplatePath & strFile2
On Error Resume Next
Set WordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set WordApp = CreateObject("Word.Application")
End If
On Error GoTo ErrHandler
WordApp.Visible = True
WordApp.WindowState = wdWindowStateMaximize
WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True
'strJobTitle = DLookup("JobTitle", "Job", "JobNum = " & [JobType])
strJobTitle = DLookup("JobTitle", "Job", "JobNum = 'J0456'")
With WordApp.Selection
'Unprotect the file
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
.Goto what:=wdGoToBookmark, Name:="bm_0_4"
.TypeText strJobTitle
End With
'Reprotect the document.
'If ActiveDocument.ProtectionType = wdNoProtection Then
'ActiveDocument.Protect _
'Type:=wdAllowOnlyFormFields, NoReset:=True, Password:=""
'End If
DoEvents
WordApp.Activate
Set WordApp = Nothing
Exit Sub
ErrHandler:
Set WordApp = Nothing
End Sub
Thank You
I haven't tried this but WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True does return the new document. So I would do something like
Dim doc as Word.Document
Set doc = WordApp.Documents.Add(Template:=strTemplate, NewTemplate:=True)
and reference doc throughout my code instead of ActiveDocument. It seems like doing that should get help you avoid the particular situation you're concerned about.

Download files from a web page using VBA HTML

I have been trying desperately for months to automate a process whereby a csv file is downloaded, maned and saved in a given location.
so far I only managed with excel vba to open the web page and click the bottom to download the csv file, but the code stop and required a manual intervention to to be completed, i would like it to be fully automated if possible.
see the code used (I am not the author):
Sub WebDataExtraction()
Dim URL As String
Dim IeApp As Object
Dim IeDoc As Object
Dim ieForm As Object
Dim ieObj As Object
Dim objColl As Collection
URL = "http://www.bmreports.com/bsp/BMRSSystemData.php?pT=DDAD&zT=N&dT=NRT"
Set IeApp = CreateObject("InternetExplorer.Application")
IeApp.Visible = True
IeApp.Navigate URL
Do Until IeApp.ReadyState = READYSTATE_COMPLETE
Loop
Set IeDoc = IeApp.Document
For Each ele In IeApp.Document.getElementsByTagName("span")
If ele.innerHTML = "CSV" Then
Application.Wait (Now + TimeValue("0:00:15"))
DoEvents
ele.Click
'At this point you need to Save the document manually
' or figure out for yourself how to automate this interaction.
Test_Save_As_Set_Filename
File_Download_Click_Save
End If
Next
IeApp.Quit
End Sub"
thanks in advance
Nunzio
I am posting a second answer, since, as I believe my first answer is adequate for many similar applications, it does not work in this instance.
Why the other methods fail:
The .Click method: This raises a new window which expects user input at run-time, it doesn't seem to be possible to use the WinAPI to control this window. Or, at least not any way that I can determine. The code execution stops on the .Click line until the user manually intervenes, there is no way to use a GoTo or a Wait or any other method to circumvent this behavior.
Using a WinAPI function to download the source file directly does not work, since the button's URL does not contain a file, but rather a js function that serves the file dynamically.
Here is my proposed workaround solution:
You can read the webpage's .body.InnerText, write that out to a plain text/csv file using FileSystemObject and then with a combination of Regular Expressions and string manipulation, parse the data into a properly delimited CSV file.
Sub WebDataExtraction()
Dim url As String
Dim fName As String
Dim lnText As String
Dim varLine() As Variant
Dim vLn As Variant
Dim newText As String
Dim leftText As String
Dim breakTime As Date
'## Requires reference to Microsoft VBScript Regular Expressions 5.5
Dim REMatches As MatchCollection
Dim m As Match
'## Requires reference to Microsoft Internet Controls
Dim IeApp As InternetExplorer
'## Requires reference to Microsoft HTML object library
Dim IeDoc As HTMLDocument
Dim ele As HTMLFormElement
'## Requires reference to Microsoft Scripting Runtime
Dim fso As FileSystemObject
Dim f As TextStream
Dim ln As Long: ln = 1
breakTime = DateAdd("s", 60, Now)
url = "http://www.bmreports.com/bsp/BMRSSystemData.php?pT=DDAD&zT=N&dT=NRT"
Set IeApp = CreateObject("InternetExplorer.Application")
With IeApp
.Visible = True
.Navigate url
Do Until .ReadyState = 4
Loop
Set IeDoc = .Document
End With
'Wait for the data to display on the page
Do
If Now >= breakTime Then
If MsgBox("The website is taking longer than usual, would you like to continue waiting?", vbYesNo) = vbNo Then
GoTo EarlyExit
Else:
breakTime = DateAdd("s", 60, Now)
End If
End If
Loop While Trim(IeDoc.body.innerText) = "XML CSV Please Wait Data Loading Sorting"
'## Create the text file
fName = ActiveWorkbook.Path & "\exported-csv.csv"
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(fName, 2, True, -1)
f.Write IeDoc.body.innerText
f.Close
Set f = Nothing
'## Read the text file
Set f = fso.OpenTextFile(fName, 1, False, -1)
Do
lnText = f.ReadLine
'## The data starts on the 4th line in the InnerText.
If ln >= 4 Then
'## Return a collection of matching date/timestamps to which we can parse
Set REMatches = SplitLine(lnText)
newText = lnText
For Each m In REMatches
newText = Replace(newText, m.Value, ("," & m.Value & ","), , -1, vbTextCompare)
Next
'## Get rid of consecutive delimiters:
Do
newText = Replace(newText, ",,", ",")
Loop While InStr(1, newText, ",,", vbBinaryCompare) <> 0
'## Then use some string manipulation to parse out the first 2 columns which are
' not a match to the RegExp we used above.
leftText = Left(newText, InStr(1, newText, ",", vbTextCompare) - 1)
leftText = Left(leftText, 10) & "," & Right(leftText, Len(leftText) - 10)
newText = Right(newText, Len(newText) - InStr(1, newText, ",", vbTextCompare))
newText = leftText & "," & newText
'## Store these lines in an array
ReDim Preserve varLine(ln - 4)
varLine(ln - 4) = newText
End If
ln = ln + 1
Loop While Not f.AtEndOfStream
f.Close
'## Re-open the file for writing the delimited lines:
Set f = fso.OpenTextFile(fName, 2, True, -1)
'## Iterate over the array and write the data in CSV:
For Each vLn In varLine
'Omit blank lines, if any.
If Len(vLn) <> 0 Then f.WriteLine vLn
Next
f.Close
EarlyExit:
Set fso = Nothing
Set f = Nothing
IeApp.Quit
Set IeApp = Nothing
End Sub
Function SplitLine(strLine As String) As MatchCollection
'returns a RegExp MatchCollection of Date/Timestamps found in each line
'## Requires reference to Microsoft VBScript Regular Expressions 5.5
Dim RE As RegExp
Dim matches As MatchCollection
Set RE = CreateObject("vbscript.regexp")
With RE
.MultiLine = False
.Global = True
.IgnoreCase = True
'## Use this RegEx pattern to parse the date & timestamps:
.Pattern = "(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])[ ]\d\d?:\d\d:\d\d"
End With
Set matches = RE.Execute(strLine)
Set SplitLine = matches
End Function
EDIT
I tested my original answer code using the URL:
http://www.bmreports.com/bsp/BMRSSystemData.php?pT=DDAD&zT=N&dT=NRT#saveasCSV
But this method does not seem to work, for this site. The ele.Click doesn't seem to initiate the download, it just opens the data tabular on the webpage. To download, you need to do the right-click/save-as. If you have gotten that far (as I suspect, based on the subroutines you are calling, but for which you did not provide the code), then you can probably use the Win API to get the HWND of the Save dialog and possibly automate that event. Santosh provides some information on that:
VBA - Go to website and download file from save prompt
Here is also a good resource that should help solve your problem:
http://social.msdn.microsoft.com/Forums/en-US/beb6fa0e-fbc8-49df-9f2e-30f85d941fad/download-file-from-ie-with-vba
Original Answer
If you are able to determine the URL of the CSV then you can use this subroutine to open a connection to the CSV data and import it directly to the workbook. You may need to automate a text-to-columns operation on the imported data, but that can easily be replicated with the macro recorder. I put an example of this in the Test() subroutine below.
You could easily modify this to add the QueryTables in a new workbook, and then automate the SaveAs method on that workbook to save the file as a CSV.
This example uses a known URL for Yahoo Finance, Ford Motor Company, and will add a QueryTables with the CSV data in cell A1 of the active worksheet. This can be modified pretty easily to put it in another sheet, another workbook, etc.
Sub Test()
Dim MyURL as String
MyURL = "http://ichart.finance.yahoo.com/table.csv?s=GM&a0&b=1&c2010&d=05&e=20&f=2013&g=d&ignore=.csv"
OpenURL MyURL
'Explode the CSV data:
Range("A:A").TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=False, Comma:=True, Space:=False, Other:=False, FieldInfo _
:=Array(Array(1, 3), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), _
Array(7, 1)), TrailingMinusNumbers:=True
End Sub
Private Sub OpenURL(fullURL As String)
'This opens the CSV in querytables connection.
On Error GoTo ErrOpenURL
With ActiveSheet.QueryTables.Add(Connection:= _
"URL;" & fullURL, Destination:=Range("A1"))
.Name = fullURL
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = True
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.WebSelectionType = xlEntirePage
.WebFormatting = xlWebFormattingAll
.WebPreFormattedTextToColumns = True
.WebConsecutiveDelimitersAsOne = True
.WebSingleBlockTextImport = False
.WebDisableDateRecognition = False
.WebDisableRedirections = False
.Refresh BackgroundQuery:=False
End With
ExitOpenURL:
Exit Sub 'if all goes well, you can exit
'Error handling...
ErrOpenURL:
Err.Clear
bCancel = True
Resume ExitOpenURL
End Sub