I've been struggling to find a way to open a Read-only document in Normal/Edit mode instead of Reading mode with MS Word 2013. Word 2013 by default enables the start up option to "Open e-mail attachments and other uneditable files in reading view".
How would I go about disabling this option or changing the view from Reading to Normal/Edit view when the document is opened. (I need to keep the document as read-only as it might be accessed by multiple people at once)
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open(documentPath,,True)
objWord.ActiveWindow.ActivePane.View.Type = wdNormalView
I have tried to set the view mode using the above but received the an error code shown below. I looked at other variations of line 3 but can't get it to work. I'm still working my way around learning VBScript so I'm assuming i'm not doing this the right way.
Error: One of the values passed to this method or property is out of range
Code: 800A16D3
Source: Microsoft Word
Thanks.
You're using VBScript - it doesn't understand what wdNormalView means. This is an internal value for VBA. You need to find the actual value held for this constant and apply that instead. The constant is a WdViewType and the values are as follows:
Name Value Description
wdMasterView 5 A master view.
wdNormalView 1 A normal view.
wdOutlineView 2 An outline view.
wdPrintPreview 4 A print preview view.
wdPrintView 3 A print view.
wdReadingView 7 A reading view.
wdWebView 6 A Web view.
So the option you want to select is 1. Try the following code and see if this works:
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Open(documentPath,,True)
objWord.ActiveWindow.ActivePane.View.Type = 1
Related
Through a VBS code I need to check out some data models from the power designer.
The requirements are: Connect to the power designer repository, check out some data models. can anybody help me?
I found this code in SAP documentation, but when i execute it the following error appears.
Dim rc : Set rc = RepositoryConnection
'Check out model
Dim TargetModel
Set TargetModel = rc.FindChildByPath("MyFolder/MyPDM", PdRMG.Cls_RepositoryModel)
TargetModel.CheckOut()
Output "Checked"
The error messege:
Microsoft VBScript Runtime Error
Required object (0x800A01A8)
on line 5
As mentioned by the first comment, at least, verify the FindChildByPath return value:
Set TargetModel = rc.FindChildByPath("MyFolder/MyPDM", PdRMG.Cls_RepositoryModel)
if targetmodel is nothing then
output "nothing"
else
TargetModel.CheckOut()
Output "Checked out"
end if
Apart from that, the sample works for me, and opens the PDM I have checked in.
I'm trying this:
Dim oApp
Dim iReturnedResult
Set oApp = CreateObject("Some.Application")
Set F_Ord = oApp.Documents.Open("Window 1", VarPtr(iReturnedResult))
The ActiveX control expects the second parameter to be a Long by reference.
This works perfectly well inside Excel VBA.
I can run this step by step, and see the result is returned like it should.
But, when I move this code to a VBS file and run it from the command line (CScript.exe), I get an error 800A000D, meaning it's the wrong type.
I have also tried creating an array instead, and tested with these commands, without any luck:
Set F_Ord = oApp.Documents.Open("Window 1", VarPtr(iReturnedResult(0)))
Set F_Ord = oApp.Documents.Open("Window 1", iReturnedResult(0))
Does anyone know how to pass a long variable by reference to an ActiveX control from VBScript?
The simple answer is VarPtr() is not supported by VBScript.
To my knowledge, there is no equivalent that allows you to pass a pointer to a variables memory address.
Useful Links
Visual Basic for Applications Features Not In VBScript
I'm trying to get Word to fill in cells in a table. The script works when run as a macro from within Word, but fails when saved as a .vbs file and double-clicked, or run with wscript. This is a part of it.
set obj = GetObject(,"Word.Application)
With obj
With .Selection
MsgBox .text
If (.Information(wdWithInTable) = True) Then
.Collapse Direction:=wdCollapseStart
tCols = .Tables(1).Columns.Count
tRow = .Information(wdStartOfRangeRowNumber)
tCol = .Information(wdStartOfRangeColumnNumber)
For I = 2 To 5
.Tables(1).Cell(tRow, I).Range.Text = "fred" & Str(I)
Next
` now make new row
For I = 1 To tCols - tCol + 1
.MoveRight unit:=wdCell
Next
End If
End With
End With
I have three problems. First, it won't compile unless I comment out the .Collapse and .MoveRight lines. Second, although the MsgBox .text displays the selected text, I get "out of range" errors if I try to access any .Information property.
I'm sure I'm missing something very simple: I usually write software for Macs, and I'd do this using AppleScript. This is my first attempt at getting anything done under Windows.
VBScript and VBA are different languages.
They are a bit similar, but not very. Moreover, VBScript is not like AppleScript; it doesn't let you easily interface with running programs.
The interfaces you'll get from VBScript can behave subtly differently in VBA and VBScript. However, I think you've got two problems here:
:= is invalid syntax in VBScript; you'll need to find an alternative way of calling the function. Try just using positional arguments.
You've no guarantee that this will open the expected file; there could be another instance of Word that it's interacting with instead.
Since your code is not running within the Word environment it would require a reference to the Word object library in order to use enumeration constants (those things that start with wd).
VBScript, however, cannot work with references, which means the only possibility is to use the long value equivalents of the enumerations. You'll find these in the Word Language References. Simplest to use is probably the Object Browser in Word's VBA Editor. (In Word: Alt+F11 to open the VBA Editor; F2 to start the Object Browser; type in the term in the "Search" box, click on the term, then look in the bottom bar.)
The code in the question uses, for example:
wdWithInTable
wdCollapseStart
wdStartOfRangeRowNumber
wdStartOfRangeColumnNumber
wdCell
The reason you get various kinds of errors depends on where these are used.
Also, VBScript can't used named parameters such as Unit:=. Any parameters must be passed in comma-delimited format, if there's more than one, in the order specified by the method or property. If there are optional parameters you don't want to use these should be left "blank":
MethodName parameter, parameter, , , parameter
I have an MDB file which contains a number of tables and forms. Each field has a validation rule such as Is Null Or >=0 And <=255.
This access database is being converted into an online system using MySQL. Exporting all the data is easy using MDBTools (https://github.com/brianb/mdbtools).
However I can't find any way of exporting the validation rules. There are thousands of fields across over 100 tables so it's going to be important to export and import them rather than rewrite each one.
I don't really mind what format they're exported in, any sort of text format so I could do a regular expression or something will be fine.
However I haven't been able to find any information anywhere on exporting these validation rules.
Perhaps if it's not built into access by default then a VB script could be used to find the info and write it to a text file? I'm not really familiar with access or windows at all so if anyone could suggest if that was a possibility that would be great.
Using VBA allows you to retrieve field validation rules directly.
I realize it's probably too late to help you now. And, although it may not seem appropriate for someone unfamiliar with Access and VBA, this approach requires only a table, copying the code below into a standard module, and running it. So someone else may benefit.
I created my table, field_validation_rules, to store the text of the validation rule properties. The table includes 3 text fields: table_name; field_name; and validation_rule.
Public Sub GatherValidationRules()
Dim db As DAO.Database
Dim fld As DAO.Field
Dim rs As DAO.Recordset
Dim tdf As DAO.TableDef
Set db = CurrentDb
Set rs = db.OpenRecordset("field_validation_rules", dbOpenTable, dbAppendOnly)
For Each tdf In db.TableDefs
If Not (tdf.Name Like "~*" Or tdf.Name Like "MSys*") Then
For Each fld In tdf.Fields
If Len(fld.ValidationRule) > 0 Then
rs.AddNew
rs!table_name.Value = tdf.Name
rs!field_name.Value = fld.Name
rs!validation_rule.Value = fld.ValidationRule
rs.Update
End If
Next
End If
Next
rs.Close
End Sub
The ValidationRule property is a string value. If the property has not been assigned for a given field, ValidationRule is an empty string. The code skips those, storing only validation rules for fields which have them assigned.
If you want the collected validation rules in a text file, there a several options. I dumped mine to CSV like this:
DoCmd.TransferText acExportDelim, , "field_validation_rules", "C:\share\Access\field_validation_rules.txt", False
To anyone else finding this, this is how I wound up doing it. This was in Access 2003, it may be different in other versions.
First I went to Tools > Analyze > Documenter selected the table I wanted and used these settings:
I was then presented with what looked like a pdf or word doc (I don't think it is, but it doesn't really matter).
I then did File > Export and selected "Text Files .txt" and saved it to a location on my computer.
I then opened the .txt file in PHP (anywhere you can do regular expressions should be fine).
In my instance not every single field had validation rules and the validation rules did not appear if they were not set, which meant a regular expression to fetch the fieldID had more results than to fetch the validation rules.
So I used two regular expressions.
/SourceField:\s+(\S+).*?AllowZeroLength/msi
This gets everything betwenen SourceField and AllowZeroLength. AllowZeroLength is the first bit of repeating text after the validation rules.
I then used this regular expression to get the validation rules from within that string.
/ValidationRule:\s+(.*)\\r/
I had to use \r instead of new line, probably something to do with moving it from Windows to Ubuntu.
In PHP it looked like this:
<?php
$file_contents = file_get_contents('validations.txt');
$response = [];
preg_match_all('/SourceField:\s+(\S+).*?AllowZeroLength/msi', $file_contents, $matches);
for($i = 0; $i < count($matches[0]); $i++) {
$id = $matches[1][$i];
preg_match('/ValidationRule:\s+(.*)\\r/', $matches[0][$i], $validation_match);
$response[$id] = $validation_match[1] ?? null;
}
There is almost certainly a cleaner regular expression than this, but this was incredibly quick and I got exactly what I wanted.
I am currently trying you learn VB6 and came across this issue.
I wanted to loop through a for loop and adding a number to a control name.
Dim I As Integer
For I = 1 To 5
S = CStr(I)
If TextS.Text = "" Then
LabelS.ForeColor = &HFF&
Else
LabelS.ForeColor = &H80000012
End If
Next I
This S needs to be added to Text and Label so the colour will be changed without needing to use 5 If Else statements
I hope you can help me with this.
From your comment below:
What i mean is this: If Text1.text = "" Then I need this 1 to be replaced with the variable I, so the for loop can loop through my 5 textboxes and the same for my Labels.
You can't do that (look up a variable using an expression to create its name) in VB6. (Edit: While that statement is true, it's not true that you can't look up form controls using a name from an expression. See "alternative" below.)
What you can do is make an array of your textboxes, and then index into that array. The dev env even helps you do that: Open your form in the dev env and click the first textbox. Change its name to the name you want the array to have (perhaps TextBoxes). Then click the next textbox and change its name to the same thing (TextBoxes). The dev env will ask you:
(Don't ask me why I have a VM lying around with VB6 on it...)
Click Yes, and then you can rename your other textboxes TextBoxes to add them to the array. Then do the same for your labels.
Then your code should look like this:
For I = TextBoxes.LBound To TextBoxes.UBound
If TextBoxes(I).Text = "" Then
Labels(I).ForeColor = &HFF&
Else
Labels(I).ForeColor = &H80000012
End If
Next
LBound is the lowest index of the control array, UBound is the highest. (You can't use the standard LBound and Ubound that take the array as an argument, because control arrays aren't quite normal arrays.) Note also that there's no need to put I on the Next line, that hasn't been required since VB4 or VB5. You can, though, if you like being explicit.
Just make sure that you have exactly the same number of TextBoxes as Labels. Alternately, you could create a user control that consisted of a label and a textbox, and then have a control array of your user control.
Alternative: : You can use the Controls array to look up a control using a name resulting from an expression, like this:
For I = 1 To 5
If Me.Controls("Text" & I).Text = "" Then
Me.Controls("Label" & I).ForeColor = &HFF&
Else
Me.Controls("Label" & I).ForeColor = &H80000012
End If
Next
This has the advantage of mapping over to a very similar construct in VB.Net, should you migrate at some point.
Side note:
I am currently trying you learn VB6...
(tl;dr - I'd recommend learning something else instead, VB6 is outdated and the dev env hasn't been supported in years.)
VB6's development environment has been discontinued and unsupported for years (since 2008). The runtime is still (I believe) supported because of the sheer number of apps that use it, although the most recent patch seems to be from 2012. But FWIW, you'd get a better return on your study time learning VB.net or C#.Net (or any of several non-Microsoft languages), rather than VB6...