Access Rich-/HTML-Textbox does indents bulleted lists with wrapped text incorrectly (1 Viewer)

sonic8

AWF VIP
Local time
Tomorrow, 00:00
Joined
Oct 27, 2015
Messages
350
Access Rich-/HTML-Textbox indents bulleted lists with wrapped text incorrectly

Hi Everyone!

I'm pretty annoyed by the fact that the Access Rich-/HTML-Textbox seems to be unable to indent bulleted lists with wrapped text correctly. If a line is wrapped, the second line will start at the indention level of the bullet point but not at the indention level of the text in the previous line.


Note: Text was formatted by using the formatting tool bar of the textbox itself. There was no custom HTML involved. The HTML of the Webbrowser control is the exact same as in the textbox.

Code:
<ul>
 <li>This is a long bullet point item and wrapped text looks horrible because it is not indented to the level of the text in the first line.</li>
 <li>It looks even worse if there are multiple bullet points with long text</li>
 <li>An some with short text</li>
 <li>And long text again that will once again get wrapped </li>
</ul>
This is bearable during data entry in the form, but the entered text must be printed on a report where this just looks horrible.

Core question: How do I display HTML with correctly formatted bulleted lists in a report?

Using a Webbrowser control instead of the standard Access Textbox would be the obvious solution. However, it seems to be impossible to use the Webbrowser control in a report.

BTW: I made Microsoft aware of this issue some time ago, but nothing improved so far.

Best regards,
Philipp
 

Attachments

Last edited:

MajP

You've got your good things, and you've got mine.
Local time
Today, 18:00
Joined
May 21, 2018
Messages
3,139
if you want it to be specifically formatted, then using an Access report is pretty limited. Just learn to automate Word as your report writer. Then you will have total control of your output. Or just continue to complain.
 

isladogs

CID Moderator
Staff member
Local time
Today, 23:00
Joined
Jan 14, 2017
Messages
13,153
Hi Phillip
I haven't tried your bulleted lists example but perhaps you can use the same method I do to print the output from a form with web browser control

For example - form with web browser and print button



The output can be sent direct to the printer or do a print preview:



Code used:
Code:
Private Sub cmdPrint_Click()

On Error GoTo Err_Handler

    If Me.WebBrowser0.visible = True Then
        'print
        'Me.WebBrowser0.Object.Document.execCommand "Print"  ', False, True
        'print preview
        Me.WebBrowser0.ExecWB OLECMDID_PRINTPREVIEW, OLECMDEXECOPT_DONTPROMPTUSER
    End If

Exit_Handler:
    Exit Sub

Err_Handler:
    MsgBox "Error " & Err.Number & " in cmdPrint_Click procedure : " & _
             & Err.description, vbCritical, "Program error"
    Resume Exit_Handler

End Sub
I use this idea in several apps where I have a form with a web browser
Do you think you could make use of the same approach?
 

Attachments

Last edited:

isladogs

CID Moderator
Staff member
Local time
Today, 23:00
Joined
Jan 14, 2017
Messages
13,153
Two more web browser examples from a different app that are perhaps more like what you are trying to do

1. Form:


Print preview:


2. Form:


Print preview:


Obviously with this approach you need to put all the information in the web browser control on the form.
AFAIK there is no method of suppressing or modifying the print header/footer sections but I'd be pleased to hear from anyone who knows how to do so.
 

Attachments

CJ_London

Super Moderator
Staff member
Local time
Today, 23:00
Joined
Feb 19, 2013
Messages
12,092
@Colin - that doesn't seem to preserve the indent if the text wraps?
 

isladogs

CID Moderator
Staff member
Local time
Today, 23:00
Joined
Jan 14, 2017
Messages
13,153
What I was trying to show was that the print out is identical to the text on the web browser form no matter what the layout is.
If the text is indented in the first place (mine wasn't), it will be when printed.

EDIT:
To make my point more clearly, here is an example similar to Phillip's original:





In my apps, the text was entered on a rich text memo control on a separate form to that shown but displayed on a web browser control. This is to allow for formatted text plus images and hyperlinks as required. Due to the method of data entry I didn't use tags such as <li>, <ul> etc when creating the text.

Hope that helps
 

Attachments

Last edited:

sonic8

AWF VIP
Local time
Tomorrow, 00:00
Joined
Oct 27, 2015
Messages
350
Aesthetics are a very subjective matter, so maybe my words were somewhat stronger and more emotional than appropriate.

Still, the notion voiced by some that if I expect a rather simple HTML/Rich-Text to be formatted correctly, I should not use Access, is a view I do not share. - Even though, considering reality, it might be the right advice.

Just learn to automate Word as your report writer. Then you will have total control of your output.
I haven't tried your bulleted lists example but perhaps you can use the same method I do to print the output from a form with web browser control
Thank you both for these generally valid suggestions.


Unfortunately, replacing the Access report engine altogether is hardly possible in my scenario. The report I want to print consists of multiple nested sub-reports and makes extensive use of Access's group sections as well as extending and shrinking areas. The text area containing the formatted HTML is just a small but important part of it. - The HTML aside, the Access report engine does an excellent job in rendering this report!
Replicating this entire report in either HTML or MS-Word will take days if not weeks.

Thinking about the problem and the responses I received inspired me to a potential solution with splitting the text programmatically and using multiple records in in a sub-report to display it. - Just some crazy idea yet, but I will explore it some more if I find the time.

BTW: Another idea I had to solve this, was using the Webbrowser control to render the HTML, take a screenshot of the output, and insert the screenhot into a picture area of the report. - The main case against investigating this further is that the text in the image will not be easily copy-able if the report is stored as an PDF.
 
Last edited:

isladogs

CID Moderator
Staff member
Local time
Today, 23:00
Joined
Jan 14, 2017
Messages
13,153
Unfortunately, replacing the Access report engine altogether is hardly possible in my scenario.

BTW: Another idea I had to solve this, was using the Webbrowser control to render the HTML, take a screenshot of the output, and insert the screenhot into a picture area of the report. - The main case against investigating this further is that the text in the image will not be easily copy-able if the report is stored as an PDF.
Your other idea was going to be my next suggestion if you couldn't replace the Access report completely but I'd also hesitated for exactly the same reason

Good luck with finding a solution
 

CJ_London

Super Moderator
Staff member
Local time
Today, 23:00
Joined
Feb 19, 2013
Messages
12,092
Only thing I can suggest is to do some string manipulation. Using VBA, parse or split the string on "<ul>" (I think), determine how many characters can be shown on the first row and <blockquote> to move the following row(s) across.

Just using the richtext ribbon can't create the required code but for example

I can convert this


to this

by changing this code
Code:
="<ul><li>this is just some plain text and more</li></ul>"
to

Code:
="<ul><li>    this is just some</li></ul><blockquote>plain text and more</blockquote>"
by adding spaces to the first line, blockquote to the following lines and moving </li></ul>. You could use non breaking spaces instead of blockquote which will reduce the space between dot and text, but then you would have to do so for every line

The trick is to know where to break it. It may be you can parse on a set number of characters or perhaps adapt code from Stephen Lebans here
http://www.lebans.com/autosize_textbox.htm

that will calculate what to resize a textbox control to to fit the text - but should be able to use the same principle to determine the number of characters on a row.

Not ideal, but might be a way forward for you
 

Attachments

sonic8

AWF VIP
Local time
Tomorrow, 00:00
Joined
Oct 27, 2015
Messages
350
Only thing I can suggest is to do some string manipulation. Using VBA, parse or split the string on "<ul>" (I think), determine how many characters can be shown on the first row and <blockquote> to move the following row(s) across.
CJ, Thank you!
This looks very promising. I wasn't aware that the textbox supports the blockquote element. I will try to explorer this further as soon as I find the time.
 

sonic8

AWF VIP
Local time
Tomorrow, 00:00
Joined
Oct 27, 2015
Messages
350
I've not abandoned this topic. It just was very frustrating (and unsuccessful so far) get some detail to work so far.
The trick is to know where to break it. It may be you can parse on a set number of characters or perhaps adapt code from Stephen Lebans here
http://www.lebans.com/autosize_textbox.htm

that will calculate what to resize a textbox control to to fit the text - but should be able to use the same principle to determine the number of characters on a row.
I think, unfortunately, Stephen's code cannot be used in this context. It retrieves the area required to display a certain text. However, for the purpose discussed here, I need to retrieve the text that will fit into a certain area (line). In theory, the GetTextExtentExPoint-API-Function should be able to do that. In practice however, it crashes Access more often than not. I was unable to figure that one out, yet.
 

isladogs

CID Moderator
Staff member
Local time
Today, 23:00
Joined
Jan 14, 2017
Messages
13,153
There is another very powerful approach you should consider.
The hidden undocumented Wizhook function includes a TwipsFromFont property which you can use to get the exact height or width of any character in any font.

I used it to get the precise height of a font as part of this example app http://www.mendipdatasystems.co.uk/move-forms-controls/4594549378.
The purpose in that case was to be able to 'select' listbox items just by moving the mouse over the list.
In that sample, Stephen Lebans code just wasn't accurate enough to be reliable. Wizhook was perfect!

Although I haven't needed to do so, you could also use it to determine the number of characters in a row and therefore where a line break is required.

NOTE you will need to include the Wizhook key using the line
Code:
    WizHook.Key = 51488399
Hope that helps you solve your problem
 

CJ_London

Super Moderator
Staff member
Local time
Today, 23:00
Joined
Feb 19, 2013
Messages
12,092
depends on the font type/size you are using but perhaps based on the widest character ('W' ?) you can used a fixed 'row length'.

Based on parsing the string you could do something like

Code:
function convertStr(rt as string) as string
dim s as string
dim t as string
dim i as integer
dim l as integer
dim j as integer

const rowlength=80 'characters that can appear on one row of control - can adjust for 'avg' width of character
const spaces=4 'to add after dot, might vary depending on font type/size

i=1
while i<len(rt)-8

    if mid(rt,i,8)="<ul><li>" then 'found one
        i=i+8 'adjust position
        t=mid(rt,i,instr(mid(rt,i+spaces),"</li></lu>")-1)'text in one block
        s=s & "<ul><li>" & space(spaces) 'add dot and spaces to new string
        
        'add text
        
         j=len(left(t,rowlength-spaces-1) 'max number of chars to copy, 1 is for the dot
         j=j-instrrev(left(t,j)," ") - adjust to finish on a word end
         s=s & left(t,j) & "</li></lu>" 'add text to new string
         i=i+j 'adjust position
         'remove copied text from string
          if j<len(t) then t=mid(t,j+1) else t=""
          
          if len(t)>0 then 'add blockquote
              
              s=s & "<blockquote>" & t &  "</blockquote>"
              i=i+len(t)'edit might need to add 10 to skip over </li></lu>
          end if
    end if
    s=mid(rt,i,1)
    i=i+1

wend
convertStr=s & right(rt,8)

end function
the above is aircode, not tested so may have errors but what I envisaged you might do

you would populate your control source with the function

=convertStr([mymemofield])
 

isladogs

CID Moderator
Staff member
Local time
Today, 23:00
Joined
Jan 14, 2017
Messages
13,153
The advantage of using the Wizhook function for this is that you don't need to estimate the width. It is precisely calculated for whatever text you enter including any capitals etc and is done for the font name, size and style used.

As I said I've only used it for font height rather than width but its fast and I don't believe there will be any noticeable processing time even for a lengthy string.
 

sonic8

AWF VIP
Local time
Tomorrow, 00:00
Joined
Oct 27, 2015
Messages
350
depends on the font type/size you are using but perhaps based on the widest character ('W' ?) you can used a fixed 'row length'.
[...]

Code:
const rowlength=80 'characters that can appear on one row of control - can adjust for 'avg' width of character
This assumption is exactly the point I'm struggling with. I rather want to calculate the length of the actual string instead of hard-coding this.


The advantage of using the Wizhook function for this is that you don't need to estimate the width. It is precisely calculated for whatever text you enter including any capitals etc and is done for the font name, size and style used.
That is the right approach, but it is the wrong way round. I have fixed bounds (the width of the textbox) and want to know what part of my string will fit in there.


Yes, I could start with a reasonable assumption and then use TwipsFromFont in a loop to fine tune that to the actual measurement. - That would be a workaround, but not as elegant as I hoped for.
 

isladogs

CID Moderator
Staff member
Local time
Today, 23:00
Joined
Jan 14, 2017
Messages
13,153
That is the right approach, but it is the wrong way round. I have fixed bounds (the width of the textbox) and want to know what part of my string will fit in there.

Yes, I could start with a reasonable assumption and then use TwipsFromFont in a loop to fine tune that to the actual measurement. - That would be a workaround, but not as elegant as I hoped for.
Yes I realise that you actually want 'FontFromTwips' but I don't think thw workround is likely to be too complex

If you haven't yet done so, have a look at the 2 Wizhook links in my website article. The 2nd link is a PDF which won't allow me to quote from it but here's an extract as a screenshot:



The extract also contains two functions

I have the A2000 Developers Handbook but haven't looked at that chapter recently. If you don't have the book, let me know & I'll look whether there is any additional code that may be useful to you
 

Attachments

CJ_London

Super Moderator
Staff member
Local time
Today, 23:00
Joined
Feb 19, 2013
Messages
12,092
This assumption is exactly the point I'm struggling with. I rather want to calculate the length of the actual string instead of hard-coding this.
I realise that, just offering it as a suggestion.

the wizhook approach would mean this constant would be replaced with some sort of wizhook function
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Top Bottom