Ask Your Question
0

Get Selected Text Boxes and Combine into One

asked 2019-01-07 16:22:42 +0100

starryknight64 gravatar image

updated 2019-01-07 20:50:40 +0100

Hello! I'd like to write a macro that combines the text boxes I've selected into one and remove the uncombined text boxes. This is using LO Draw.

I'm not new to Excel VBA or Python (preferred) but I am new to LO Basic. If I could just get started that'd be great. For instance, I don't know how to get the current selection or make a new text box.

Or, even better, if someone wants to write up such a macro that'd be awesome! :) Thanks in advance!

EDIT: An uncombined text box is a list of 2 or more selected text boxes in "viewing" order. i.e. top-to-bottom, left-to-right. Assume the text boxes do not overlap.

FURTHER CLARIFICATION: My use case is to select multiple text boxes and combine them into a singular text box and then remove the original text boxes that were selected. The combined text box should have the aggregate of all the text contained by the original selected text boxes.

By viewing order I am talking about reading order. I wouldn't want the aggregation of the text to be in the wrong order, after all. This is why I say "top-to-bottom, left-to-right" as this is the natural order in which I read English. Furthermore, you are right in that I cannot assure anything. However, if the solution comes close then I can potentially further refine it to be acceptable.

edit retag flag offensive close merge delete

Comments

What do you mean by "combine ... text boxes"? What is an uncombined text box? Unselected in this case?
It's not difficult. Basically. If I assume you want the texts from the selected shapes accumulated into one, you may want to get these texts in a specific order. There are mainly two orders that may be different: The "logical order" in which the shapes originally were created, and the "order as viewed" after the shapes were moved into their current positions. What about overlapping (probably 100%)?
Programming often is simple - as long as you don't worry about malfunctions probably occurring due to unsufficiently considered "exceptional" cases.

Lupp gravatar imageLupp ( 2019-01-07 16:41:27 +0100 )edit

Added clarification. Also just realized that LO allows for Python scripts to be ran? That'd be preferred if it's possible...

starryknight64 gravatar imagestarryknight64 ( 2019-01-07 17:05:21 +0100 )edit

It's strange. I used LibreOffice and (mostly) its predecessors a lot when I was still in office, but I never had need to program for it. The very few programming I did in the context of administration was in Pascal and Delphi.
Now I am long retired, and only due to contributing to some forums - and sometimes a bit for fun - I started to create user code now and then for AOO or LibO. If I do so, I use Basic - and, of course the uno-API which is needed in most cases independent of what language / IDE is used. In fact the API would be in the center of any solution for your task, and neither Python nor Basic nor C++ can do much for you beyond organising some loops and branchinjgs. These languages / implementations / run-time libraries ... are useful if you need to to things that are not well ...(more)

Lupp gravatar imageLupp ( 2019-01-07 19:03:28 +0100 )edit

Quoting @starryknight64: "EDIT: An uncombined text box is a list of 2 or more selected text boxes ..."
I didn't understand that. Are you sure you wanted to tell exactly this?
Quoting @starryknight64: "... in 'viewing' order i.e. top-to-bottom, left-to-right. Assume the text boxes do not overlap."
I would see the two quoted text pieces as basically independent statements, the first one unclear in terms, the second one doubtable: You may assume as you like. If you cannot assure it, a solution should not rely on it.

Lupp gravatar imageLupp ( 2019-01-07 19:09:49 +0100 )edit

Thanks for all your help so far, @Lupp! Here's some further clarification:

My use case is to select multiple text boxes and combine them into a singular text box and then remove the original text boxes that were selected. The combined text box should have the aggregate of all the text contained by the original selected text boxes.

By viewing order I am talking about reading order. I wouldn't want the aggregation of the text to be in the wrong order, after all. This is why I say "top-to-bottom, left-to-right" as this is the natural order in which I read English. Furthermore, you are right in that I cannot assure anything. However, if the solution comes close then I can potentially further refine it to be acceptable.

starryknight64 gravatar imagestarryknight64 ( 2019-01-07 20:35:28 +0100 )edit

If you can not assure that the viewing-order = reading-order is identzivcal with the insertion-order = logical-order, you need to sort using the .Position coordinates (.X and .Y) as sort-keys.
This is done in the demonstration I already pointed you to.
A simplified vesrion omitting the sorting, but accumulating the texts into thelogically-last shape , and deleting all the other selected shapes is attached to my answer by editing.

Lupp gravatar imageLupp ( 2019-01-07 21:47:35 +0100 )edit

2 Answers

Sort by » oldest newest most voted
0

answered 2019-01-07 19:25:51 +0100

Lupp gravatar image

updated 2019-01-07 21:59:10 +0100

To make this more substantial:
There was the thread https://ask.libreoffice.org/en/questi... to which I posted an answer first, and later amended a note doing the "pdf" from the original subject aside. This note is enriched by a demonstartion how text from graphical shapes (in a draw document) can be extracted and accumulated.

The output there is done to a newly created Writer document. Of course, it would also be possible to use another ShapeText for the output. Just do it if you want. The code in the mentioned demo is public domain. If you can assure that the visible order of your shapes is concordant with the logical order, you can omit the sorting (which is the only part for which I actually wrote code not related to the API, and which might be done more efficiently by some ready-made Python function). If you can assure that the shapes you want to assemble text from never are grouped, you also can omit the recursive functions resolving the groups. (This was the part I was mainly interested in when I wrote the code.)

===Edit1 2019-01-07 21:50 CET===
I attach this demonstration of a simplified solution announced in my recent comment on the question.
Please note that none of the examples I gave worries about internal formatting or contained textfields (links). Everything is prefixed to the content of the final shape taking the character properties set there.
If you need the sorting, see the older demo I already pointed you to.

edit flag offensive delete link more

Comments

The only thing I didn't do in my solution was use text cursors. Any particular reason I should? Would doing so potentially preserve formatting options like bold for instance?

starryknight64 gravatar imagestarryknight64 ( 2019-01-07 23:06:08 +0100 )edit

Hmmm. To do a next step after some years I prepared the example originally trying to find a way to also move TextPortions which may simply be differently formatted TextRanges or TextFields like text which represents a background URL (the only type of fields that also may occur in TextShape). For that purpose I would need to create TextContent and to insert it at a cursor position. In cases of uniformity and assured no links can occur, you can simply concatenate the strings.
However, I left the topic without a solution for the extended task. I "lost the impetus". Again no progress insofar.

Lupp gravatar imageLupp ( 2019-01-08 01:48:49 +0100 )edit
0

answered 2019-01-07 23:04:45 +0100

starryknight64 gravatar image

Thank you so much @Lupp! You got me what I needed!

Here's what I ended up with after everything was said and done:

REM  *****  BASIC  *****

Sub doIt()
    If NOT ThisComponent.supportsService("com.sun.star.drawing.DrawingDocument") Then Exit Sub

    curSel = ThisComponent.CurrentSelection
    curSelCount = curSel.Count
    If curSelCount <= 0 Then Exit Sub

    firstSel = curSel(0)
    firstSel.TextAutoGrowWidth = False
    firstSel.TextAutoGrowHeight = True

    For i=1 to curSelCount - 1
        sel = curSel(i)
        firstSel.String = firstSel.String + " " + Trim(sel.String)

        if sel.Size.Width > firstSel.Size.Width then
            firstSel.Size.Width = sel.Size.Width
        end if

        sel.Parent.remove(sel)
    Next i

    while InStr(firstSel.String, "  ") <> 0:
        firstSel.String = Replace(firstSel.String, "  ", " ")
    wend
End Sub

Function Replace(Source As String, Search As String, NewPart As String)
    Dim Result As String  
    Result = join(split(Source, Search), NewPart)
    Replace = Result
End Function
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2019-01-07 16:22:42 +0100

Seen: 49 times

Last updated: Jan 07