Getting the Height of the Detail Section After CanGrow/CanShrink (1 Viewer)

nathan.malone

New member
Local time
Today, 13:49
Joined
Apr 5, 2018
Messages
6
I have an MS Access report with a detail section that automatically adjusts its height to fit its contents using the CanGrow and CanShrink properties. The report is about ongoing projects within the company, and the height of the detail section can fluctuate substantially for each project. Additionally, there are two versions of this report: general and administrative. The administrative version has some information that the general version does not have, which causes height differences for the same projects between the two versions. My current task is to make the height of the detail section for each project match between the two versions of the report, even if the contents don't match.

My current idea to approach this problem is to record the height of the detail section of each project on the administrative report, then run the general report and set the height of each detail section to match the recorded heights from the administrative report. To do this, I have to determine the height of the detail section AFTER the section has automatically adjusted its height, which is the keystone that I cannot figure out. The reason that I put emphasis on the word "after" is that, in my experience, the Detail.Height property during the Detail.OnFormat event does not reflect the height of the detail section after the section adjusts to fit its contents, but rather it reflects the height of the detail section before it adjusts to fit its contents (effectively giving me the height that I assigned to it in design view).

I have been beating my head against the wall with this problem for far too long. How do I get the height of the detail section after it has automatically adjusted to fit its contents? Alternatively, is there a better approach to making the corresponding detail sections between the two report versions match in height?
 

MarkK

bit cruncher
Local time
Today, 11:49
Joined
Mar 17, 2004
Messages
8,181
My current idea to approach this problem is to record the height of the detail section of each project on the administrative report, then run the general report and set the height of each detail section to match the recorded heights from the administrative report.
The approach I would take instead is to simply set the ForeColor the same as the BackColor for any controls that you want to have not appear. Then the amount of space they take up remains the same, but they just don't appear in the print. Recording all the sizes and then resizing everything in the abridged version seems like a total headache.

I have been beating my head against the wall...
I would venture to suggest that as a problem-solving strategy, this leaves a lot to be desired. Instead, consider the advantages of poking yourself eye with a sharp stick, or beating your head with a more robust tool, like a hammer or a wrench.

hth
Mark
 

isladogs

MVP / VIP
Local time
Today, 19:49
Joined
Jan 14, 2017
Messages
18,213
Cross posted with answers at http://www.accessforums.net/showthread.php?t=71472

There is nothing wrong with cross posting but you could have the courtesy of saying you have done so and providing the link.

Perhaps you could now do so at the other forum
 

nathan.malone

New member
Local time
Today, 13:49
Joined
Apr 5, 2018
Messages
6
Cross posted with answers at (link to other post)

There is nothing wrong with cross posting but you could have the courtesy of saying you have done so and providing the link.

Perhaps you could now do so at the other forum

Will do. I'm new to both platforms and did not know that mentioning a cross-post is a standard, but I'll start doing it now. The time stamps should show it, but I initially created the post here and only posted to the other platform when I hadn't received a reply in a day. Thanks for the tip.

Edit: After attempting to reply to your comment, I have found out that I'm actually not allowed to post links due to having fewer than 10 posts. (Note that I had to remove the link above.)
 
Last edited:

nathan.malone

New member
Local time
Today, 13:49
Joined
Apr 5, 2018
Messages
6
The approach I would take instead is to simply set the ForeColor the same as the BackColor for any controls that you want to have not appear. Then the amount of space they take up remains the same, but they just don't appear in the print. Recording all the sizes and then resizing everything in the abridged version seems like a total headache.

This was actually an approach that I considered but didn't mention in the original post for the sake of brevity. The only problem that I see with this approach is that each version of the report is exported as a printed copy (which this would work for) and a PDF. The information that is hidden is sensitive, and the text would still exist as a PDF (I think), so (in theory) someone could still edit the document to show the text.
 

isladogs

MVP / VIP
Local time
Today, 19:49
Joined
Jan 14, 2017
Messages
18,213
Will do. I'm new to both platforms and did not know that mentioning a cross-post is a standard, but I'll start doing it now. The time stamps should show it, but I initially created the post here and only posted to the other platform when I hadn't received a reply in a day. Thanks for the tip.

Edit: After attempting to reply to your comment, I have found out that I'm actually not allowed to post links due to having fewer than 10 posts. (Note that I had to remove the link above.)

Have you tried the similar solution I proposed in the other forum where selected controls are hidden in the Detail Format event I.e. after the section height is finalised.

Doing so will I believe solve your concerns about being able to make those items visible again in the PDF as I don't think they can be highlighted/edited in any way. In fact I don't think they will actually exist in the PDF (not tested)

I use a similar setup to optionally anonymise report data and there have been no security issues reported by end users
 

nathan.malone

New member
Local time
Today, 13:49
Joined
Apr 5, 2018
Messages
6
Have you tried the similar solution I proposed where selected controls are hidden in the Detail Format event I.e. after the section height is finalised.

Doing so will I believe solve your concerns about being able to make those items visible again in the PDF as I don't think they can be highlighted/edited in any way. In fact I don't think they will actually exist in the PDF (not tested)

I use a similar setup to optionally anonymise report data and there have been no security issues reported by end users

I have not yet had a chance to attempt any of the proposed solutions. I have been on another project the past few days and was trying to put feelers out for ideas in the meantime. I'm hoping to get some time to work on this problem this afternoon and report back to both posts.

Thanks for the suggestions.
 

nathan.malone

New member
Local time
Today, 13:49
Joined
Apr 5, 2018
Messages
6
I have finally worked out a solution to this. I hope there is not a rule on line limits. If so, I will gladly edit my post to attach the code as a file instead.

Effectively, my approach was not to hide the controls, but rather count how many lines would go into those controls if I did show the administrative information, and replace those lines with dummy blank lines. Below is a simplified version of the code I used in my Detail.OnFormat event. Note, txtId, txtAdminNotes, and txtAdminNotesLabel are all textboxes on my form. All administrative controls are set with Visible, CanGrow, and CanShrink equal to True.

Code:
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
    Dim sql As String
    Dim rs As DAO.Recordset
    Dim adminNotes As String
    
    sql = "SELECT * " & _
            "  FROM [My_Table] " & _
            " WHERE [Id] = " & txtId.value
    
    Set rs = CurrentDb.OpenRecordset(sql, dbOpenSnapshot, dbSeeChanges)
    
    If Not rs.BOF Or Not rs.EOF Then
        rs.MoveFirst

        'Get special administrative notes.
        adminNotes = Nz(rs!STIP_Comments_Internal, vbNullString)
        
        'Add special administrative information (or blank lines) to the report.
        HandleAdministrativeTextBox adminNotes, txtAdminNotes, "Admin. Notes:", txtAdminNotesLabel
    End If
End Sub

Below you will find the helper subs that I used that actually do the majority of the work. I broke them out into reusable subs because there is more than one set of controls for which I used this same logic.

Code:
Private Sub HandleAdministrativeTextBox(ByRef textVal As String, _
                                        ByRef txtBox As TextBox, _
                                        labelText As String, _
                                        txtBoxLabel As TextBox)
    Dim lineCount As Long
    textVal = BreakTextToFitTextBox(textVal, txtBox, lineCount)
    
    If isAdministrative Then
        'Add administrative information to the report.
        txtBox.value = textVal
        txtBoxLabel.value = IIf(Len(textVal), labelText, vbNullString)
    Else
        If Len(textVal) Then
            'Add blank lines to the report.
            If lineCount <> 1 Then
                txtBox.value = GenerateBlankLines(lineCount)
            Else
                'Single blank line. (Trivial; avoid unnecessary function call)
                txtBox.value = " "
            End If
        Else
            txtBox.value = vbNullString
        End If
    End If
End Sub

Private Function GenerateBlankLines(numLines As Long) As String
    Dim blankLines As String
    Dim index As Long
    
    For index = 1 To numLines
        blankLines = blankLines & IIf(index <> 1, vbCrLf, vbNullString) & " "
    Next
    
    GenerateBlankLines = blankLines
End Function

Private Function BreakTextToFitTextBox(ByRef textVal As String, _
                                       ByRef txtBox As TextBox, _
                                       Optional ByRef numLines As Long = 0) As String
    Dim brokenTextVal As String
    Dim lineCount As Long
    
    If InStrB(textVal, " ") Then
        Dim words() As String
        Dim wordIndex As Long
        Dim currentWord As String
        Dim lines() As String
        Dim currentLine As String
        Dim testLine As String
        
        'Sync the formatting between the report and the textbox
        'since the report is the object that measures the text.
        Me.FontName = txtBox.FontName
        Me.FontSize = txtBox.FontSize
        Me.FontBold = txtBox.FontBold
        Me.FontItalic = txtBox.FontItalic
        
        'Split the text on spaces.
        words = Split(textVal, " ")
        lineCount = 0
        ReDim lines(lineCount) As String
        
        'Loop through the words (or otherwise cluster of characters) one by one.
        For wordIndex = LBound(words) To UBound(words)
            currentWord = words(wordIndex)
            
            'Test if the word can fit in the textbox with the current line.
            'NOTE: The "+ 100" that you see below is a hack. For some reason,
            '      the measurement didn't work perfectly. This seemed to work
            '      in most cases, but there is probably a better solution
            '      somewhere out there to be discovered.
            testLine = IIf(Len(currentLine), currentLine & " ", vbNullString) & currentWord
            If txtBox.Width > Me.TextWidth(testLine) + 100 Then
                'It fit. Add the word to the line and move on.
                currentLine = testLine
            Else
                'It didn't fit. Start a new line with the current word.
                lineCount = lineCount + 1
                ReDim Preserve lines(lineCount) As String
                
                lines(lineCount - 1) = currentLine
                currentLine = currentWord
            End If
        Next
        
        'Cleanup: Make sure to add the last line to the lines array.
        If Len(currentLine) Then
            lineCount = lineCount + 1
            ReDim Preserve lines(lineCount) As String
            
            lines(lineCount - 1) = currentLine
        End If
        
        'Concatenate the lines array with vbCrLf.
        brokenTextVal = Join(lines, vbCrLf)
    Else
        'No spaces to split the text on.
        lineCount = IIf(Len(textVal), 1, 0)
        brokenTextVal = textVal
    End If
    
    numLines = lineCount
    BreakTextToFitTextBox = brokenTextVal
End Function
 

nathan.malone

New member
Local time
Today, 13:49
Joined
Apr 5, 2018
Messages
6
Please view the solution and the discussion on the solution on the other thread. (Link provided by ridders above.)
 

pbaldy

Wino Moderator
Staff member
Local time
Today, 11:49
Joined
Aug 30, 2003
Messages
36,125
Post 9 was moderated, I'm posting to trigger email notifications.
 

Users who are viewing this thread

Top Bottom