Set MS Access form property using VBScript - forms

I'm trying to edit .NavigationButtons property of multiple MS Access Form objects using VBScript.
Here's my startup code:
Dim access
Set access = CreateObject("Access.Application")
access.OpenCurrentDatabase "d:/mydb.accdb"
Now when database is open I can access it's forms by calling .CurrentProject.AllForms of Application object. This method returns a collection of AccessObject objects. I can set their properties by simply calling .Properties.Add method, but it sets the property of AccessObject and it's not what I want.
I also tried to loop through .Forms property of Application object. This property stores a collection of forms with real form properties and .NavigationButtons is one of them. However, this collection is read-only and I can't set new values to these properties.
Is there any way to update Form property from VBScript program?

Finally, I was able to make it work using both .CurrentProject.AllForms and .Forms methods of Application object. I was missing one detail - you have to save form after you changed it's property.
For Each form.Name access.CurrentProject.AllForms
access.DoCmd.OpenForm form.Name, 1
access.Forms(form.Name).NavigationButtons = True 'Or another property.
access.DoCmd.Close 2, form.Name, 1 'Where "1" is equal to acSaveYes.
Next

Related

Powershell enumerate properties of properties

I have a commandlet that gathers information from a device register:
PS C:\windows\system32> Get-PSDevice serverA
HostName: ServerA
OOB:
Criticality: Normal
IsVirtual: True
etc
Some of these have an array of 'sub properties' inside, for example:
Cluster : #{Url=https://ps-apps.com/DeviceRegister/api/Clusters/62; VCenterUrl=https://ps-apps.com/DeviceRegister/api/VCenters/2; ClusterId=62; VCenterId=2; Name=Vcenter 1 ABC Prod;
DataCenterUrl=https://ps-apps.com/DeviceRegister/api/DataCenters/3; DataCenter=; IsValidated=True; IsExceptionCluster=False; SupportsProdWorkloads=False; SupportsNonProdWorkloads=False; SupportsSqlWorkloads=False;
ManagedByabc=False}
I can get whatever property within the aray I want using something like:
(Get-PSDevice ServerA).cluster.name
I'm trying to determine a way to enumerate all of the sub properties using a foreach type statement to populate a value.
What would be the best way to achieve this?
Every object in PowerShell has a hidden .PSObject property which tells you things about the object. One of its properties is a .Properties property (as PetSerAl points out, it's not a property but in fact a MemberSet, though you access it with property semantics).
(Get-PSDevice ServerA).cluster.PSObject.Properties
That would return [PSProperty] objects that show you the information about the properties (the name, value, type, whether it's gettable and settable, etc.).

Does model.getProperty() return a live object for objects that are members of an array?

I get an object from within an array in my model (a JSONmodel type) which is
{
"task": [
{
"dbid": 465,
"bk_cnt": 11,
}, {
"dbid": 472,
"bk_cnt": 16,
}
]
}
I bind this model to a table and connect the bk_cnt up to an objectNumber in a cell. No problem so far.
In code I want to change the value of the first bk_cnt value from 11 to 20 on press of a button. Inside the event I have:
var model = this.getView().getModel() // get the model
var tasks = model.getProperty("/task"); // get as a JS object
tasks[0].bk_cnt = 20 // update the model...will it update the view?
// model.refresh() // it will if this is uncommented.
Problem: Though it is bound to the view, the displayed value of bk_cnt does not change. if I add model.refresh() it does. This code is extracted from a larger section and one of the larger features is sorting by column click. When I click a column to re-sort (no change to the model), the value 20 appears.
What gives?
Musings: I have read that the model.getProprty() function returns a javascript object with a live reference back to the model, and that a change to the value of the object will automatically be reflected in the view for any bound controls. Does this statement fall down on array attributes ?
EDIT: Still feeling around the issue I find that
model.setProperty("/task/0/bk_cnt", 20)
Does not require a model.refresh() to update the view. Not a total surprise as this command is directly acting through the model. This leaves me thinking that the 'live' object returned by getProperty() is only live when it is a primitive datatype like a string or integer, but not for a JS object. Or am I missing something ?
EDIT 2: #Ash points out in his answer that there is a further approach which is to access the JS object from the model property, set whatever attributes need to be updated in the JS object, then replace that into the model, e.g.
var tasks = model.getProperty("/task");
tasks[0].bk_cnt = 20
model.setProperty('/task', tasks)
Second edit done to complete the trio of approaches for future readers.
The Model object is an abstraction layer ON TOP of a javascript object. There is no way that a change within an object is notified anywhere. You need to explicitly trigger the notifications through model.refresh() or model.setProperty().
So both of your solutions are valid, another one (which I favor) would be
var tasks = model.getProperty("/task");
tasks[0].bk_cnt = 20
model.setProperty('/task', tasks)
But this actually depends on how you bind your model to your UI objects :)

Passing arguments to Access Forms created with 'New'

I have a form called 'detail' which shows a detailed view of a selected record. The record is selected from a different form called 'search'. Because I want to be able to open multiple instances of 'detail', each showing details of a different record, I used the following code:
Public detailCollection As New Collection
Function openDetail(patID As Integer, pName As String)
'Purpose: Open an independent instance of form
Dim frm As Form
Debug.Print "ID: " & patID
'Open a new instance, show it, and set a caption.
Set frm = New Form_detail
frm.Visible = True
frm.Caption = pName
detailCollection.Add Item:=frm, Key:=CStr(frm.Hwnd)
Set frm = Nothing
End Function
PatID is the Primary Key of the record I wish to show in this new instance of 'detail.' The debug print line prints out the correct PatID, so i have it available. How do I pass it to this new instance of the form?
I tried to set the OpenArgs of the new form, but I get an error stating that OpenArgs is read only. After researching, OpenArgs can only be set by DoCmd (which won't work, because then I don't get independent instances of the form). I can find no documentation on the allowable parameters when creating a Form object. Apparently, Microsoft doesn't consider a Constructor to be a Method, at least according to the docs. How should I handle this? (plz don't tell me to set it to an invisible text box or something) Thanks guys, you guys are the best on the net at answering these questions for me. I love you all!
Source Code for the multi-instance form taken from: http://allenbrowne.com/ser-35.html
Inside your Form_detail, create a custom property.
Private mItemId As Long
Property Let ItemID(value as Long)
mItemId = value
' some code to re query Me
End Property
Property Get ItemId() As Long
ItemId = mItemId
End Property
Then, in the code that creates the form, you can do this.
Set frm = New Form_detail
frm.ItemId = patId
frm.Visible = True
frm.Caption = pName
This will allow you to pass an ID to the new form instance, and ensure it gets requeried before making it visible. No need to load all of the results every time if you're always opening the form by Newing it. You let the property load the data instead of the traditional Form_Load event.
This works because Access Form modules are nothing more than glorified classes. Hope this helps.
You could try applying a filter:
frm.Filter = "[ID] = " & patID
frm.FilterOn = True
The Record Source of the Detail form will need to be set to the table to which the ID belongs.
UPDATE
As you requested, here is the code to set the RecordSource:
frm.RecordSource = "select * from TableName where [ID] = " & patID
This is probably cleaner than using a filter given that a user can remove the filter (depending on the type of form).

Check for list of String in DataAnnotation

I need to check whether the Property contains one of the or all following strings
"C-I", "C-II", "C-III", "C-IV", "C-V"
if not it Errormessage must be
"Invalid Property. Must be blank or C-I, C-II, C-III, C-IV, or C-V.",
i don know which "DataAnnotation Attribute" to use and How? if possible please provide sample.
You could use the Regular Expression data annotation. However, I would recommend implementing IValidatableObject on your data class. You can then write your custom logic within the Validate method. This way, if/when those valid options change, you would just be modifying a collection, rather then trying to figure out a new valid regex statement.
It can be done using anyone of the follwing Attributes
**
1.EnumDataTypeAttribute
2.CustomValidationAttribute
3. Creating New Custom Attribute.
**

How to specify computed property dependency in EmberJS on an array of objects that contain another array

I am using EmberJS and I am trying to setup the dependency on a computed property. A visitor can contain multiple tickets (an array), and I have access to an object containing an array of visitors. This is my computed property. How can the property be recomputed when a ticket is added to any of the visitors in the visitors array?
App.AttendanceController = App.SlideBaseController.extend
eligibleVisitors:
(->
return #getElegibleVisitors()
).property('App.state.session.visitors.#each.type')
allEligibleVisitorsAttending:
(->
return _.all #getElegibleVisitors(), (visitor)->
return visitor.tickets.length > 0 and _.any visitor.tickets, (ticket)->
return ticket.EventID is content.Event.ID
).property('App.state.session.visitors.tickets')
getElegibleVisitors:->
return _.filter App.state.session.visitors, (visitor)->
return visitor.type isnt App.VisitorTypes['Infant']
Something like this should work:
.property('App.state.session.visitors.#each.tickets.#each')
Updates when any ticket is added to any visitor.
AFAIK this is not possible right now and won't be for Ember 1.0. See here: https://github.com/emberjs/ember.js/issues/541
Nested #each properties don't trigger observers correctly.
I faced a similar problem (nested tree structure) -- I got around it by having each child node have a reference property to the parent node, and then adding
Node = Ember.Object.extend
nodeParent: null # to point at parent
nodeChanged: (->
#get('nodeParent')?.notifyPropertyChange 'notifier'
).observes 'various', 'properties
I used 'notifier' as a general key that other properties on the parent can bind to; when things in the child change, it causes a property change on the parent.notifier, which will in turn trigger other properties you want.
This is a hacky work around. Plus side is that it works, downside is you have to keep track of the child-parent relationship; i.e., for you, each Ticket needs to a reference to its Visitor