Move an Object from Form Detail to Header in Code (1 Viewer)

Cotswold

Active member
Local time
Today, 10:34
Joined
Dec 31, 2020
Messages
528
I can move an Object around the Detail section of a form with VBA but I can't just see how to move it from the Detail section to the Header or Footer section.
If I manually shift the Object into the Header, I can then move it about there but as I say failing to move it from Detail to Header, or Footer and vice versa with code. A pointer for the code required appreciated.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 04:34
Joined
Feb 28, 2001
Messages
27,191
OK, the problem is the nature of headers and detail sections. They are separate objects. They act like separate, independent canvases. All locations on a form (based on Top, Left coordinates) are section-relative. Using VBA, you cannot move anything from one section to another because doing so would be a change of .Parent object.

You can of course use design mode to do a cut/paste of the object - cut from one section and paste to another. However, to actually do a VBA move of an object across sections in form view is not recommended. You can easily get the effect by having two identical objects (one in header, one in detail) and make only one of them visible at a time.

Our member MajP is also a member of other forums. He fielded a similar question back in 2015 from the Tek-Tips forum. Rather than repeat the by-play here, I offer the link.


The short answer is, strictly speaking you cannot do exactly what you asked. You have to do something else that looks similar. And, if the form lives long enough, you reach the lifetime object limit for adding objects to a section.
 

Minty

AWF VIP
Local time
Today, 10:34
Joined
Jul 26, 2013
Messages
10,371
Is this just for presentation differences under different conditions?
If so, simply have two copies of the control and hide and unhide it based on the conditions.
 

Cotswold

Active member
Local time
Today, 10:34
Joined
Dec 31, 2020
Messages
528
Thanks Minty but that wouldn't help. No doubt in common with everyone else, I have several standard forms and each will usually have a set of seven or more set buttons, plus [Exit]. i.e [Edit], [Add], [Save], [Cancel] etc.

There are seven possible locations for the buttons and OnOpen() they are automatically set to one of those and spaced out depending upon the operation and screen use. The location of the buttons are set automatically and also adjusted in relation to screen size if I change it. So if I add or delete buttons, or change the screen size the button set will sort itself out automatically from wherever they may be lying on the form. Each button has its own standard Sub(), or Function(), so hiding, or duplicates etc will only add unnecessary complication.

It appears from TheDocMan & MajP that if I want them in the Header or Footer I'll need to drag them there and then run the button placement function OnOpen(), which isn't a great problem as it is only ever done once for each new form when they are created. Plus not many developed forms actually have a Header or Footer anyway. I'll stop experimenting now. If TDM & MajP say it won't work then it won't. Should have posted it yesterday!

It would have been nice to just stick them automatically where I decide I want them on each new form I created copied from a standard form without any effort from myself. The more code I can automate the better I like it........particularly the boring bits:)
(ps thanks to TDM as well.)
 
Last edited:

isladogs

MVP / VIP
Local time
Today, 10:34
Joined
Jan 14, 2017
Messages
18,235
You could create two template forms and use them for all new forms - one with the objects in the detail section and the other in the header
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 05:34
Joined
May 21, 2018
Messages
8,529
It seems like a no brainer to me or maybe I am missing something? You have two sets of buttons (one in header/footer, one in the detail) and show and hide the ones you need. I would not have two templates because then you have configuration management issues.
 
Last edited:

Cotswold

Active member
Local time
Today, 10:34
Joined
Dec 31, 2020
Messages
528
It seems like a no brainer to me or maybe I am missing something? You have two sets of buttons (one in header/footer, one in the detail) and show and hide the ones you need. I would not have two templates because then you have configuration management issue
No, one set of buttons only! I only need one set of buttons that I can move about on a form using code OnOpen but I cannot move them using code into the header. Two would be pointless. As I have said I can obviously drag them from Detail to Header and then set their position with code. I have one template of this particular form and if I need a Header or Footer for the application I just add them.

Really I should have realised when I found that I couldn't Set Focus to the Header itself. I can obviously Setfocus to an object in the Header but not to the actual Header or Footer. From that I should have spotted I cannot, with code, move an object there but clearly I didn't.

( In an attempt to remove confusion I attach some screen shots. )
 

Attachments

  • ButtonsSet.pdf
    54.3 KB · Views: 89
Last edited:

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 04:34
Joined
Feb 28, 2001
Messages
27,191
You cannot set focus to a section as it is not a control. You can set focus to a whole form if and only if there are no enabled controls on it.
 

Uncle Gizmo

Nifty Access Guy
Staff member
Local time
Today, 10:34
Joined
Jul 9, 2003
Messages
16,282
Each button has its own standard Sub(), or Function(), so hiding, or duplicates etc will only add unnecessary complication.

If you separate the button code out into independent standalone functions then you can call that function from any buttons you desire.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 05:34
Joined
May 21, 2018
Messages
8,529
No, one set of buttons only! I only need one set of buttons that I can move about on a form using code OnOpen but I cannot move them using code into the header. Two would be pointless.
That statement is absolutely ridiculous!
I will say it one more time.
Have two sets of buttons! Header and footer buttons, and Detail buttons. And be done with it.
DTM.gif


If you have any reason why not, please advise. The solution with that method would have taken 30 seconds.
If you want to get fancy have a single event handler (using a common function) and use the Tag property to determine what to do.
 

Gasman

Enthusiastic Amateur
Local time
Today, 10:34
Joined
Sep 21, 2011
Messages
14,311
Why is no one thinking this is a design issue disaster?
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 05:34
Joined
May 21, 2018
Messages
8,529
Maybe I Am missing something, but this seems trivial. See if this demo suffices.
I would however have all the buttons react to a single event handler
Code:
Private Function ClickButton()
 Dim ctrl As Access.Control
 Set ctrl = Me.ActiveControl
 Select Case ctrl.Tag
   Case "Save"
     MsgBox "Save"
   Case "Filter"
     MsgBox "Filter"
   Case "Delete"
     MsgBox "Delete"
 End Select
End Function

So any button that is a Save button is tagged "Save"

Pass in the template condition then determine which ones to show (all buttons are hidden and stacked in left corner to start). Then move and show.
Code:
Private Sub Form_Load()
  If (Me.OpenArgs & "") <> "" Then
    Select Case Me.OpenArgs
    Case "1"
      loadCase1
    Case "2"
      loadCase2
    Case "3"
      loadCase3
    End Select
  End If
 
End Sub
Private Function ClickButton()
 Dim ctrl As Access.Control
 Set ctrl = Me.ActiveControl
 Select Case ctrl.Tag
   Case "Save"
     MsgBox "Save"
   Case "Filter"
     MsgBox "Filter"
   Case "Delete"
     MsgBox "Delete"
 End Select
End Function

'-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'---------------------------------------------------------------------------- Template Conditions ---------------------------------------------------------------------------------

Public Function loadCase1()
  'Header right
  MsgBox "Right aligned Header"
  Me.Section(acHeader).Visible = True
  With cmdSaveHdr
    .Visible = True
    .Left = 6240
    .Top = 420
 End With
 With CmdDeleteHdr
    .Visible = True
    .Left = 7080
    .Top = 420
 End With
 With cmdFltrHdr
    .Visible = True
    .Left = 7920
    .Top = 420
 End With
End Function
Public Function loadCase2()
  'No Header right buttons
  Me.Section(acHeader).Visible = False
  MsgBox "Bottom Left Detail"
   With cmdSave
    .Visible = True
    .Left = 7860
    .Top = 5400
 End With
 With cmdDelete
    .Visible = True
    .Left = 7860
    .Top = 5880
 End With
 With cmdFltr
    .Visible = True
    .Left = 7860
    .Top = 6360
 End With
End Function

Public Function loadCase3()
   MsgBox "Upper Left Detail"
   Me.Section(acHeader).Visible = False
    With cmdSave
    .Visible = True
    .Left = 60
    .Top = 60
 End With
 With cmdDelete
    .Visible = True
    .Left = 60
    .Top = 540
 End With
 With cmdFltr
    .Visible = True
    .Left = 60
    .Top = 1020
 End With
End Function
 

Attachments

  • TemplateButtons.accdb
    436 KB · Views: 120

GPGeorge

Grover Park George
Local time
Today, 02:34
Joined
Nov 25, 2004
Messages
1,873
That statement is absolutely ridiculous!
I will say it one more time.
Have two sets of buttons! Header and footer buttons, and Detail buttons. And be done with it.
View attachment 105611


If you have any reason why not, please advise. The solution with that method would have taken 30 seconds.
If you want to get fancy have a single event handler (using a common function) and use the Tag property to determine what to do.
This whole discussion smacks of one of the most common problems we encounter in this and other forums. It's a reflection of human nature, I suppose.

Frequently , less experienced Access developers come up with an approach they want to use and insist on being given the magic code to make that solution work, regardless of the availability of a superior alternative.

That happens with table design, code and interface design, pretty much every aspect of the application.
 

Gimlett

New member
Local time
Today, 10:34
Joined
Feb 25, 2011
Messages
21
Chortle, the trouble is George you just keep enabling us (I can only speak for myself of course) by being so helpful!:)
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 05:34
Joined
Feb 19, 2002
Messages
43,293
No, one set of buttons only! I only need one set of buttons that I can move about on a form using code OnOpen
I agree with the others. This is bad design on several levels, not to mention preventing you from using .accde's. You seem to be reusing one form for multiple purposes. This causes pathological coupling. When you make objects unnecessarily depend on other objects, you always risk that changes made to one object will break the other. When you see new bugs raised in Access, ask yourself, was the programmer actually changing this "feature" or was he changing something else and broke this one as a side effect?

When you reuse an object and find yourself having to use If statements in the code to take different paths, you have implemented reuse IN-correctly (typo correction). Reused objects need to be black boxes. The code outside of them decides whether to call BoxA or BoxB. BoxX doesn't decide to do processA or processB.
 
Last edited:

Cotswold

Active member
Local time
Today, 10:34
Joined
Dec 31, 2020
Messages
528
@PatH : I do not use the same form for multiple purposes, or reuse any form and fail to understand how this opinion arose.

The form as presented and discussed is a "Template-Form" with standard Buttons, 'Private Functions and Subs', which is copied to create, usually, new Modal Forms.

As a "for-instance" ; I will copy the 'Template-Form' to create a new form called F80Client, or copy it to create a new form called F10Stock. To each of those I will 'independently' add new objects, Fields, Datasheets etc, to develop the new screen in order to complete the operations specifically required by that screen for the application. I may also make amendments to my standard Functions and Subs on the new 'individual and separate' forms, if necessary

The Template-Form contains only Objects, Functions and Subs that will all be common to any new form. There aren't any Fields, Datasheets or other operation-specific Objects on the Template-Form. These would be added as I say, as and when required to F80Client and F10Stock, in the above scenario.

Most of the button Private Functions and Subs are from the original Template-Form, and are the same on whichever form I create from the Template-Form and each separate new form has no link to another.

For example, if the [Edit] button Disables the [Add], [Refresh], [Delete], [Filter], [Print], and [Exit], whilst Enabling the [Save], and [Cancel] that is clearly and obviously the exact same operation for every form in the system. I can only reiterate that all forms are totally unrelated to all others and never reused. There is no re-use of any form at all in any of my systems. Why would I? Cannot see the point in doing so. Of course, in the case of [Edit] after setting buttons as above, a unique and additional Private Sub is required to switch on the editing to the Objects which will clearly need to be different when you consider what the forms called F10Stock and F80Client are likely to contain.

My point is, why re-type, or cut and paste those exact same Subs into each new form? Or even waste any time positioning and aligning buttons if that work can be be completed automatically and without the need to amend, or test?.............Pointless.

I cannot have the EditOnOff() as a Public Function in a Module that all forms use because it is possible that some forms will have less, or additional buttons to the basic standard from the Template-Form. SO the EditOnOff() Function/Sub has to be specific and Private to each new individual form.

Goodness me, the only issue I had at the start was the hope of discovering how I could move an object from Detail to Header, or Footer using code. This was specifically and correctly solved in Post#2 by The Doc Man. A fact I confirmed on Post#4. Furthermore, my form was also correctly identified by Isladogs as a 'Template Form' in Post#5

It has now turned in to a flamin' nightmare. I will certainly give great consideration before posting anything new ever again.
 
Last edited:

isladogs

MVP / VIP
Local time
Today, 10:34
Joined
Jan 14, 2017
Messages
18,235
@Cotswold
For your purposes, I think the little known (and even less often used) Application Parts feature would be ideal.
As previously suggested in post #5, create two versions of this and save each as an application part template.
That is intended for easy access for objects that you wish to reuse on a regular basis
Each will then be available for importing into any new database

1673171249457.png


In fact, by chance, I'm in the middle of creating a new web page provisionally called Application Parts and Templates

Hope that helps
 

Cotswold

Active member
Local time
Today, 10:34
Joined
Dec 31, 2020
Messages
528
In fact, by chance, I'm in the middle of creating a new web page provisionally called Application Parts and Templates

Hope that helps
Many thanks for your suggestions Isaladogs, much appreciated. I have looked at the MS Application Parts and their templates on and off in the past without feeling any affinity, or interest in adapting any of their work or designs. Actually, their designs leaves me cold, too simplistic and often of little practical use. Plus, I'm pretty much anti-macro, preferring Functions to macros every time.

After using Access since A97, in common with many others no doubt, I have developed my own design, look and feel. Which I do prefer of course, but am always open to include new ideas, or a different way of doing the work. Particularly if it reduces development time!

However, I take your point and will from time to time check your website with some interest for the update on your new Application Parts.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 04:34
Joined
Feb 28, 2001
Messages
27,191
When you said that this was based on a template form, it struck a chord within me. (Probably Cm7b9, a little bit sour for most tastes.)

The form as presented and discussed is a "Template-Form" with standard Buttons

I extensively used the "template" concept as a way to maintain a "look-and-feel" uniformity, and I achieved that in an app with over 40 functional forms that could potentially be used by at least some of my users (depending on their roles). You are to be lauded for considering not only the uniformity of appearance but the consistency of use. However, if this is a one-control-move-per-form case, I respectfully suggest that you are trying to over-minimize the work. If this is a single control to be in point A or point B AND it has events attached to it, then you would do better to have two templates with the two alternate placements, or have BOTH point A and point B set up in the template, but only enable one of them.

From your discussion, I have not seen that you intend to do more than a few controls per form in this way. I found it was better, developer-wise for my forms that didn't have certain features to nevertheless have those features in the template but have them disabled (yes, specifically x.Enabled=False, x.Visible=False). I didn't care that some of my code wouldn't run. But considering that most of my events used a common set of functions from a general module - for which I passed in the calling form object ByRef - the amount of "dead" code wasn't that large. Most of my events were just calling a standard action function or using a standardized error handler for reporting and logging. Depending on the actual function of the form, I would say that having a template saved me a LOT of time, ranging from 40% (on complex forms) to 60% (on simple forms).
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 05:34
Joined
May 21, 2018
Messages
8,529
My point is, why re-type, or cut and paste those exact same Subs into each new form? Or even waste any time positioning and aligning buttons if that work can be be completed automatically and without the need to amend, or test?.............Pointless.
NO one is suggesting cutting and pasting any code. In fact just the opposite. I do not think anyone is arguing with doing what you want, it is just your method. The argument that "it cannot be done" does not hold, just because you do not know how to do it. If you are willing to listen we can likely show you techniques to make this easier to build and maintain, more concise, more reusable.

It is fine to say you do not know how to do it better, or you do not want to do it differently, but please do not tell those of us who know better that it cannot be done better.

Here are two methods, but there are others. If I am going to have a group of buttons that do common activity on forms, then that code is written once and once only. Do not care if those buttons are used on 100 forms.

The easiest method is creating a subform/s

In this example there is a navigation control (does what you expect). It is two subforms. The vertical subform and the horizontal subform. For demo I dropped it on the form twice. Code is identical in both subforms. I can drop one of those subforms on any form. Takes a second.
Here is the code to make it work on each and every form

Code:

That is not a mistake. There is no code. All code is encapsulated in the subform for all 4 navigation controls and every instance afterwards. No cut and paste ever, never. I added code in the form only to color the background of each subform.
SubformNav.jpg


The second demo uses a Custom Class to trap the button event. It is more complicated if not familiar with custom classes



NavWithClass.jpg


I drop two sets of buttons on the form. In this method here is the code to control the 11 controls
Code:
Private WithEvents CustNavContTop As CustomNavigationControls
Private WithEvents CustNavContBottom As CustomNavigationControls
Private Sub Form_Load()
  Set CustNavContTop = New CustomNavigationControls
  Set CustNavContBottom = New CustomNavigationControls
  CustNavContTop.Initialize Me.cmdF, Me.cmdP, Me.cmdN, Me.cmdL, Me.txtCountTop, Me.cmdSave
  CustNavContBottom.Initialize Me.cmdFirst, Me.cmdPrevious, Me.cmdNext, Me.cmdLast, Me.txtCount
End Sub
Private Sub CustNavContTop_SaveRecord()
  'Trapped event from nav control
  MsgBox "Do something in the form if save button clicked"
End Sub

This second example show how to provide even greater flexibility. It traps the custom class Save button event.


DISCLAIMER: The above example is for demonstration purposes of encapsulating functionality in a class or subform and how to use these methods. IT IS NOT TO DEMONSTRATE the best way to make a navigation control or the best navigation control class. Trust me I know other navigation controls exist out there.


I recommend these
Custom Controls
Trapping common events

The third method is to do this in a standard module. Then pass the form reference. That is pretty common and basic.
 

Attachments

  • CustomControl.accdb
    2.4 MB · Views: 57
Last edited:

Users who are viewing this thread

Top Bottom