Results 1 to 9 of 9
  1. #1
    journeyman is offline Advanced Beginner
    Windows 11 Access 2016
    Join Date
    Dec 2022
    Posts
    82

    VBA and Java - Counting elements in Range Selection

    Hi All,

    Another pickle using Java within VBA to function within a WebBrowser control.



    In the following code sample I can select a paragraph in a WB control and modify it's class. With:

    Code:
    Dim rng As MSHTML.IHTMLTxtRange
    Dim rngElement As MSHTML.HTMLDDElement
    
    
        Set rng = Doc.Selection.createRange
        Set rngElement = rng.parentElement
    
        rngElement.ClassName = strClassName ' Set the class name however I want it.
    Thankfully, this actually works when selecting just one paragraph in the Webbrowser control. This seems to happen beacuase the parent element is actually the selected pragraph, which is fine for one paragraph, but not good for more than one.

    I want to highlight two or more paragraphs and I thought something like:

    Code:
        For i = 0 To rngElement.Children.Length - 1
            With rngElement.Children(i)
                .ClassName = strClassName
            End With
        Next i
    This was an attempt to iterate though the elements of the selection. The idea was that the rngElement contained the selection. It does not, because as I've worked out, I said Set rngElement = rng.parentElement. This now means that the selection expands to everything in the parent range.

    rng.text and rng.HTMLText returns the actual selected paragraphs - which should be able to return the selected elements - how can I use this to do it?

    rngElement.innerhtml returns all the elements within the parent.

    How can I access the classname for only the selected elements?

    I'm expecting something like Set rngElement = rng.selectedElements (but of course, there is no such thing - and that would be too easy.)

  2. #2
    Edgar is offline Competent Performer
    Windows 8 Access 2016
    Join Date
    Dec 2022
    Posts
    262
    If rng.text and rng.HTMLText have both what you want, have you tried rng.ClassName?

    Additionally, have you tried the debugger?

    Do you have a minimum reproducible file you can post?
    Please click on the ⭐ below if this post helped you.


  3. #3
    journeyman is offline Advanced Beginner
    Windows 11 Access 2016
    Join Date
    Dec 2022
    Posts
    82
    So, in my continuing trial and error I have found that rng.HTMLText will return only the selected sentence within those tags and the start\end html tags for that sentence. e.g.


    Code:
    <P class=MyClass>brown fox jumps over</P>
    The rng properties do not seem to to allow access to any of the elements of the selection.

    rng.parentElement will return all of associated siblings corresponding to the range - but does not identify only those elements that were selected (hightlighted)

    the classname is not relevant until I can find the selected children - all that does is change the class for the selected element, which I can't do becuase rng does not have an elements property for the selection.

    I think I have previous posted a cut down version of this WYSIWYG editor in the past on this site. I'll have to find it again.

  4. #4
    journeyman is offline Advanced Beginner
    Windows 11 Access 2016
    Join Date
    Dec 2022
    Posts
    82
    This is the attachment corresponding to the question.

    WB Demo 2.zip

  5. #5
    Edgar is offline Competent Performer
    Windows 8 Access 2016
    Join Date
    Dec 2022
    Posts
    262
    I'm sorry, that's a lot of code and logic to digest. It'd be preferable if you had something I can play with now.

    Maybe your answer is in htmlText, If I select the last word from the first paragraph and the first from the second paragraph, that is: "sentence...THis", I get this html snippet:
    Code:
    <P class="MsoNormal" style="margin: 0cm 0cm 8pt;"><SPAN style="mso-no-proof: yes;"><FONT
    face="Tahoma">sentence.&nbsp; </FONT></SPAN></P>
    <UL>
    <UL>
    <P><BR></P>
    <UL>
    <LI>
    <P><BR></P>
    <P class="MsoNormal" style="margin: 0cm 0cm 8pt;"><SPAN style="mso-no-proof: yes;"><FONT
    face="Tahoma">THis</FONT></SPAN></P></LI></UL></UL></UL>
    If you format that HTML snippet into something more readable, you get this structure:
    HTML Code:
    <P class="MsoNormal" style="margin: 0cm 0cm 8pt;">
      <SPAN style="mso-no-proof: yes;">
        <FONT face="Tahoma">sentence.&nbsp; </FONT>
      </SPAN>
    </P>
    <UL>
      <UL>
        <P>
          <BR>
        </P>
        <UL>
          <LI>
            <P>
              <BR>
            </P>
            <P class="MsoNormal" style="margin: 0cm 0cm 8pt;">
              <SPAN style="mso-no-proof: yes;">
                <FONT face="Tahoma">THis</FONT>
              </SPAN>
            </P>
          </LI>
        </UL>
      </UL>
    </UL>
    You could do the following:
    Assign an Id to each element. When you get the range that contains your selection, you'll also get the tags associated to your selected text along with their attributes, which includes the Id, that will make it easy for you to use document.getElementById and modify the class name associated to the elements in your selection. Just look inside the .htmlText text, get the necessary Ids and do your changes with getElementById.
    Please click on the ⭐ below if this post helped you.


  6. #6
    journeyman is offline Advanced Beginner
    Windows 11 Access 2016
    Join Date
    Dec 2022
    Posts
    82
    Thanks for your suggestions.

    you can track what I'm trying to do by highlighting two paragraphs then double click the style panel.

    The only code relevant to this question is in

    Code:
    Sub ClassHandler(strClassName As String, strFontFamily As String, strFontSize As String)

    Assign an Id to each element. When you get the range that contains your selection, you'll also get the tags associated to your selected text along with their attributes, which includes the Id, that will make it easy for you to use document.getElementById and modify the class name associated to the elements in your selection. Just look inside the .htmlText text, get the necessary Ids and do your changes with getElementById.
    This seems like the only way it could be done. I was hoping that the selection would automatically identify the properties of the range, but nothing I did worked... Assigning an ID to every tag seems overkill, but if it has to be done then I have no choice.

    I'll try this approach and abandon the question for now.

    Thanks again for helps.

  7. #7
    journeyman is offline Advanced Beginner
    Windows 11 Access 2016
    Join Date
    Dec 2022
    Posts
    82
    As a final follow-up to this question, I found:

    Code:
    Dim rng As MSHTML.IHTMLTxtRange
    Dim rngElement As MSHTML.HTMLDDElement
    
    
        Set rng = Doc.Selection.createRange
        Set rngElement = rng.parentElement
        With rngElement
       
            'Determine the ID for the selected elements
            strStyleID = "StyleID" & Int((100000 * Rnd) + 1)  ' Create a Random ID value
            If rng.HtmlText = "" Then
                 ' Provide an ID, class and fonts etc for the single selected paragraph.
                 .ID = strStyleID assign the ID to the paragraph.
            Else
                 ' loop through each instance of an ID if found to allow for the change.
                 Start = 1             Do
                    FoundPos = InStr(Start, rng.HtmlText, "<P ID=", vbTextCompare)          ' Find the start position of the ID within the selected text
                    If FoundPos > 0 Then
                        EndPos = InStr(FoundPos + 3, rng.HtmlText, " ", vbTextCompare)       ' Find the end position of the ID
                        strStyleID = Mid(rng.HtmlText, FoundPos + 6, EndPos - FoundPos - 6) ' Return Style ID
                        strLiText = .innerText
                        With Doc.getElementById(strStyleID)
                        ' .... etc... etc....
                        End with
            End if
    In this way, I can select all the required paragraphs I want, and apply the class to each one where the ID is found.

    It's messy and I hate it, but it works for lack of a cleans mean to identify the selected paragraphs. I'm sure I can find a cleaner solution, but this works for now.

    All that needs happen to to provide an ID whenever a paragraph is created to avoid unnecessary steps.

    Thanks for help

  8. #8
    Edgar is offline Competent Performer
    Windows 8 Access 2016
    Join Date
    Dec 2022
    Posts
    262
    I'm sure you can find a better way.

    Analyze basic text editors like the one I'm using to write this, which uses very basic styling methods. Others use their own markup language, like the one on AWF.

    I recommend searching for online text editors and exploring GitHub repositories to gather inspiration on applying multiple styling rules simultaneously. In the end, you'll see that it's done using class names or inline style attributes, so it's just a matter of finding the tags associated to your selection, and giving your elements an Id is a good approach, the Id attribute is precisely for finding unique elements, unlike other query methods that return an array, so I believe this is a decent approach.

    The text editor you're building is more complex than the text editor we all use for this forum, so expect some complexity, especially because it's inside a browser control. That's quite the achievement.
    Please click on the ⭐ below if this post helped you.


  9. #9
    journeyman is offline Advanced Beginner
    Windows 11 Access 2016
    Join Date
    Dec 2022
    Posts
    82
    I can find all the tags in the body, just not the selection - which is a bit confusing because the selection tags are found specifically with rng.HTMLText. I just don't known how to work with those tags. Hence the reason for the ID in each paragraph. Seems bit of an overkill to apply an ID for every para, but it works and its not very heavy.

    Anyway, I am able to select multiple paragraphs and change all classes for each one with a single click, which is exactly what I wanted, so now I have a reasonably stable word processor within Access that doesn't use Python or Java and is entirely VBA driven.

    I'll consider that a success.

    The achievement come because of help from people like yourself and a many others on this forum. So thanks greatly for your continued help!!

Please reply to this thread with any new information or opinions.

Similar Threads

  1. counting number of values in a range
    By lburch in forum Queries
    Replies: 4
    Last Post: 01-24-2021, 05:19 AM
  2. Counting in a given date range
    By QuantifyRisk in forum Reports
    Replies: 1
    Last Post: 11-25-2014, 01:48 PM
  3. Replies: 3
    Last Post: 07-18-2013, 04:21 AM
  4. Replies: 4
    Last Post: 07-18-2013, 03:14 AM
  5. Replies: 5
    Last Post: 07-05-2013, 11:16 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Other Forums: Microsoft Office Forums