Access VBA Form Controls Disabled - forms

I have a book database and a simple form to browse through it and edit or create new records. I have a 'Go to first', 'Go to previous', 'Go to next', and a 'Go to last' button. What I was wanting, was for the 'first' and 'previous' to be disabled when the user was viewing the first record, and the 'next' and 'last' disabled when viewing the last record.
I'm using this code in the 'On Current' event for the form:
Private Sub Form_Current()
If Me.CurrentRecord = 1 Then
Me.Prev_Rec.Enabled = False
Me.First_Rec.Enabled = False
Else
Me.Prev_Rec.Enabled = True
Me.First_Rec.Enabled = True
End If
If Me.CurrentRecord = Me.RecordsetClone.RecordCount Then
Me.Next_Rec.Enabled = False
Me.Last_Rec.Enabled = False
Else
Me.Next_Rec.Enabled = True
Me.Last_Rec.Enabled = True
End If
End Sub
When I open up the form (it opens to the first record), all the buttons are grayed out; however, if I fiddle with the controls (just clicking them and/or moving them) in Design mode, and then switch back, the 'next' and 'last' buttons are enabled again (I'm on the first record, so the 'first' and 'previous' buttons are disabled, as they should be). What am I doing wrong?

I suspected the initial RecordCount was not reliable because the form had not yet loaded all the rows into its recordset when you first checked RecordCount.
You were able to force the recordset to finish loading before you checked RecordCount by inserting this as the first line of the procedure ...
Me.RecordsetClone.MoveLast

Related

Quasar2 Vue3 Cypress q-popup-edit

I have the following vue template:
<template>
<q-item tag="label" v-ripple>
<q-popup-edit
v-model="model"
:cover="false"
fit
buttons
:validate="validate"
#before-show="modelProxy = model"
>
<template v-slot:title>
<div class="text-mono">
{{ name }}
</div>
</template>
<q-input
color="indigo"
v-model="modelProxy"
dense
autofocus
counter
:type="dataType ? dataType : 'text'"
:hint="hint"
:error="error"
:error-message="errorMessage"
/>
</q-popup-edit>
<q-item-section>
<q-item-label class="text-mono">{{ name }}</q-item-label>
<q-item-label v-if="offset && model && model.length > offset" caption
>...{{
model.substring(model.length - offset, model.length)
}}</q-item-label
>
<q-item-label v-else caption>{{ model }}</q-item-label>
</q-item-section>
</q-item>
</template>
I would like to perform E2E test using Cypress with the following code snippet:
it('Verify Edit Box from auto-generated page', () => {
cy.get('[data-test="popup-edit-setting-1"]').contains("Auto Generated Edit box");
cy.get('[data-test="popup-edit-setting-2"]').contains("Auto Generated Edit box (Number)");
cy.get('[data-test="popup-edit-setting-1"]').should("be.enabled"); // XXX
cy.get('[data-test="popup-edit-setting-1"]').focus().click().type("Hello");//.click("SET");
cy.get('[data-test="popup-edit-setting-1"]').find("label").should('have.value', 'Hello') // XXX
});
It stumbles on the XXX points.
#Fody's solution works but there is one minor issue. I have 2 popup edit box. One with normal string, another with only numeric. There are 2 test cases for the numeric popup editbox. One with invalid normal string entry and another with valid numbers. The problem is that at the end of the test, the numeric popup edit box does NOT return to display mode. It stays popup.
This is the way I would test q-popup-edit. I used a generic example, yours may differ in some details.
I aimed to test based on what a user sees rather than any internal class or internal properties.
The user story is:
the text to be edited has a "hand" pointer when hovered
click on it to change it from "display" mode to "edit" mode
the input is automatically focused, user can start typing
user enters some text
user clicks away and the input loses focus, goes back to "display" mode
// activate popup editor
const initialText = 'Click me'
cy.contains('div.cursor-pointer', initialText) // displayed initial text
.should('be.visible') // with hand cursor
.click()
// initial condition
cy.focused() // after click <input> should have focus
.as('input') // save a reference
.should('have.prop', 'tagName', 'INPUT') // verify it is the input
cy.get('#input')
.invoke('val')
.should('eq', initialText) // displayed text is also in the input
cy.contains('8').should('be.visible') // character count
// edit action
cy.get('#input')
.clear()
.type('test input')
cy.get('#input')
.invoke('val')
.should('eq', 'test input') // verify input
cy.contains('10').should('be.visible') // character count has changed
// back to display mode
cy.get('body').click() // go back to display mode
cy.contains('div.cursor-pointer', 'test input')
.should('be.visible')
.and('contain', 'test input') // verify display element
cy.contains('10').should('not.exist') // edit counter has gone
Notes
To start the edit, you need to identify the display-mode element. It's easiest if you have some unique text in the field, so try to arrange that in the page initial data.
If no unique text, look for a label or some other selectable element nearby then navigate to it.
If you add a data-cy attribute to the <q-popup-edit>, it will not exist in the DOM until the component enters edit-mode (so you can't use it in the initial click()).

In MS Access VBA determine the next control to have focus

Understanding the order of operations, is there a way for an OnExit or OnLostFocus script to know what control was clicked to take that focus?
I have a form that has a list box from which you have to select an item for the the rest of the data entered into the form to be saved, so that control has the focus when you open the form. If you click on any other control without selecting an item from the list, an OnExit gives you a warning that you haven't made a selection.
The problem that creates is, should you open the form and then decide you don't want it, you get that message when you close the form (either with the close button on the form or the built-in closer).
I would like to be able to tell the OnExit that either the close button has been clicked or the form itself is closing, so don't show the no entries message.
Any thoughts would be appreciated.
Not that I know of.
If your form is rather simple(not to many controls.) Move the warning out of the onExit to a sub. Call it from the other controls when they get focus. But not from the Close button.
Dim bDidUserSelectSomething As Boolean
'In the list box
Private sub ListBox1_Click()
'Do some code here
'Set the flag that they did something
bDidUserSelectSomething = True
End sub
'When you enter the other controls, check if they have done what they should have.
Private Sub TextBox1_Enter()
If bDidUserSelectSomething = False Then
'Warning
End If
End Sub
Consider altering your warning check.
Instead of an OnExit() Event of the listbox, add a validation in all other pertinent controls' BeforeUpdate() events. Usually this event is where validation checks are made.
First, build a general function behind the form that calls your warning:
Public Function WarningMessage() As Boolean
If IsNull(Me.Listbox) Then
Msgbox "Please first select an option in listbox.", vbExclamation, _
"MISSING LISTBOX SELECTION"
WarningMessage = True
Else
WarningMessage = False
End If
End Function
Then call the function to each control:
Private Sub cntr1_BeforeUpdate(Cancel As Integer)
Cancel = WarningMessage
End Sub
Private Sub cntr2_BeforeUpdate(Cancel As Integer)
Cancel = WarningMessage
End Sub
...
As you can see from above, if the listbox is null then the message appears and returns True which is passed back to the control's BeforeUpdate() subroutine to cancel the update.
Now, if there are too many controls to make this doable. Consider hiding all relevant controls in Form's OnCurrent() event except the listbox. When listbox is updated, render the other controls visible. Many softwares and web applications run dynamically like this to prevent users from missing important fields.
Private Sub Form_Current()
If IsNull(Me.listbox) Then
Me.ctnrl1.Visible = False
Me.ctnrl2.Visible = False
Me.ctnrl3.Visible = False
...
Else
Me.ctnrl1.Visible = True
Me.ctnrl2.Visible = True
Me.ctnrl3.Visible = True
...
End if
End Sub
Private Sub listbox_AfterUpdate()
Me.ctnrl1.Visible = True
Me.ctnrl2.Visible = True
Me.ctnrl3.Visible = True
...
End Sub

Validate only parts of a form

I have a rather large form, that I've broken up into individual sections with "Next" and "Back" buttons for the user to navigate each step.
Here is how I set it up to work for now:
Each section is within its own xp:panel
Each xp:panel is hidden with "display:none". The transition happens when the user clicks on "Next" or "Back" by using JQuery's fade animation
What I am trying to do is, if the user clicks on "Next" I would like to validate only the fields in the current, visible section. If the validation fails, don't transition to the next step. If the validation passes, transition to the next step.
Right now, when I click on the "Next" button, every field is being validated and the transition doesn't happen.
Is there a way, that I can only validate the fields in a certain section or would I have to use something like Don Mottolo's code snippet: http://openntf.org/XSnippets.nsf/snippet.xsp?id=ssjs-form-validation-that-triggers-errormessage-controls
Thank you for your help!
P.S.: I know I could use the CSJS portion of the onClick event of the button to run some validation, but I'd like to use the "Display Error" controls.
You could look at computing the required attribute of each control that is to be validated and have that check which button is submitting the form. Tommy Vaaland has a function that does this:
// Used to check which if a component triggered an update
function submittedBy( componentId ){
try {
var eventHandlerClientId = param.get( '$$xspsubmitid' );
var eventHandlerId = #RightBack( eventHandlerClientId, ':' );
var eventHandler = getComponent( eventHandlerId );
if( !eventHandler ){ return false; }
var parentComponent = eventHandler.getParent();
if( !parentComponent ){ return false; }
return ( parentComponent.getId() === componentId );
} catch( e ){ /*Debug.logException( e );*/ }
}
Link: http://dontpanic82.blogspot.co.uk/2010/03/xpages-making-validation-behave.html
You can look at using a client side form validation framework such as Parsley: http://parsleyjs.org
This can of course be combined with server side validation for at least the final submission.

Knockout select binding

How to prevent select change event fires when the select biding is initiated? an add button on the page that will add select dynamically to the DOM. when each select box is adding to the DOM, the change event is firing rather than I select the item from the select?
The thing is that KnockoutJS attempts to find which element of your listbox matches the requiredItem observable. There is none in the beginning, which is why it then attempts to set it to the "caption" of the listbox. You did not provide one, so it sets requiredItem to the first element of the listbox.
What you could do is add a caption item to your array:
self.requireditems = ko.observableArray([
{ desc: "Select an option from the list...", key: 0, editable: false } // ... and then all other items]);
and if you really don't want requiredItem to be updated:
self.selectedItem = ko.observable(self.requiredItems()[0]);
Then if you want to know if a valid element has been selected from the list, you could add the following property:
self.isValidSelectedItem = ko.computed(function() {
return self.selectedItem().id;
});

How do I make PDF the default export option for a Crystal Report?

I am working with CrystalDecisions.CrystalReports.Engine.ReportDocument in WinForms in Visual Studio 2008. Right now when the users click the export button the dialog defaults to saving the report as a CrystalReports formatted file. It's possible to change the selector to PDF, but the specific request that I've been given -- and I've searched for too many hours trying to find -- is to make the 'export report' dialog default to PDF format option.
Does anyone know how to do this?
As of CR XI, the only way I know is to replace the export dialog with your own. You can add your own button to the CrystalReportViewer control and hide their export button.
Here's vb.net code to replace the export button with your own button/eventhandler...
Public Shared Sub SetCustomExportHandler(ByVal crv As CrystalDecisions.Windows.Forms.CrystalReportViewer, ByVal export_click_handler As EventHandler)
For Each ctrl As Control In crv.Controls
'find the toolstrip
If TypeOf ctrl Is ToolStrip Then
Dim ts As ToolStrip = DirectCast(ctrl, ToolStrip)
For Each tsi As ToolStripItem In ts.Items
'find the export button by it's image index
If TypeOf tsi Is ToolStripButton AndAlso tsi.ImageIndex = 8 Then
'CRV export button
Dim crXb As ToolStripButton = DirectCast(tsi, ToolStripButton)
'clone the looks of the export button
Dim tsb As New ToolStripButton
With tsb
.Size = crXb.Size
.Padding = crXb.Padding
.Margin = crXb.Margin
.TextImageRelation = crXb.TextImageRelation
.Text = crXb.Text
.ToolTipText = crXb.ToolTipText
.ImageScaling = crXb.ImageScaling
.ImageAlign = crXb.ImageAlign
.ImageIndex = crXb.ImageIndex
End With
'insert custom button in it's place
ts.Items.Insert(0, tsb)
AddHandler tsb.Click, export_click_handler
Exit For
End If
Next
Exit For
End If
Next
'hide the default export button
crv.ShowExportButton = False
End Sub
Then in the click handler you'd show a customized SaveFileDialog and eventually call the ReportDocument.ExportToDisk method. This way you can set the dialog's title and filename to something useful and of course set the default export type.