How can I append a character style?

I am trying to append a (nested) character style to a word that is already part of a sentence that has a character style applied. I know how to do this manually, but need to do it with a macro.

I can get the CharStyleNames array from the paragraph section, but how do I modify it? Setting CharStyleName just overwrites the existing style.

I dont even know any way to do this manually ( in the sense: combining two CHARSTYLES into one Textportion ) ??

It can be done manually by SHIFT selecting a second style. Both styles are listed in the CharStyleNames array. I’m just not sure how to modify the CharStyleNames array in the paragraph section from a macro.

1 Like

You lost me… is it a new Gimmick mentioned here ??

So, to be less specific, I’m looking for a way to modify an array in a LO object. (Specifically, the CharStyleNames array in SwXTextPortion).

I work with both version 6.2.8.2 and 7.3.5.2 (Ubuntu 16.04)
I was unaware prior to this discussion that it was possible to apply multiple overlapping styles.
Manually, with the shift, I can only do it with 7.3.5.2, but as programming by assigning an array of styles to charStylenames, I just proved that it was already possible with 6.2.8.2
If oS is a textRange, the instruction was indeed
oS.charStylenames = array (“stylename1” , “stylename2”)

Thanks very much to moldstadt for such an important discovery, already present in HTML css, which finally simplifies the management of stylesheets even in LO.
In case of conflicts between attributes in the list of character styles (e.g. if both set charcolor in different ways) the last one in the charStylenames array prevails

See also: tdf#115311 and Writer: Combining character styles, changed behaviour?

1 Like

This works for me:

oSel = oD.currentController.selection
oPar = oSel.getByIndex (0) .textParagraph
oPar.charStyleNames = array ("stilename1", "stilename2")

It needs to be adapted to your solution with redim preserve, more accurate and general than my example

I checked with my 7.3.4.2: it doesn’t work. It used to work in 6.x releases (I don’t remember exactly which one) as an experimental feature. Howver it xas strongly recommended to not rely upon it. There are very fundamental issues with multiple character styles. I agree it would be very nice to have such a feature (as available in Quark XPress) but as soon as you edit and review your document, it becomes messy and fragmented (you have smaller and smaller <span>-like ranges in the XML), Writer being unable to merge adjacent ranges.

Superficially, it indeed seems to solve style collection management and ease design of templates, but under the hood you create many problems and perhaps you end up with an unstable document due to the present implementation.

The situation could be cleaner if user controlled exactly the extent of the <text:span> ranges. But this would be contradictory with the current GUI approach. It would be closer to TEX where macro calls are explicitly entered by user. And, once again, this would create other problems and nullify the high-level current approach to formatting.

For this reason, the multiple-character style feature has been withdrawn from Writer some time in the 7.x series. I am surprised that it is enabled in some recent versions. Perhaps an advanced setting?

Today, after reading this solution I tried it both manually and as programming in starbasic on writer 7.3.5.2 and writer 6.2.8.2 (ubuntu 16.04)
Works on both versions and both modes (manual and programming)
Manually you have to click several times with shift pressed to make it work.

The problem of fragmentation of the portions must be seen as a cost-benefit ratio, based on the use made of it and the user’s profile
In my case (personal use and knowledge of programming) it solves enough problems that I can try to use it at least for less critical applications
With the Uno Object Inspector and the Style Inspector you can get an idea of ​​the extent of the fragmentation
With programming you can build functions for paragraph scanning and relative removal of all superfluous
You can manually reapply the default character style before formatting with overlapping styles.
I will try to use this technique and I will be able to tell you in the future

I found a systematic and reliable way of applying several styles:

  1. without pressing Shift click once on the second style name
  2. with Shift pressed, double-click on selected second style name (no need to double-click several times if you preselect the second style)

With this procedure, you can even apply a third (and more) character style.
But exercise caution as it is not an official and supported feature.

1 Like

Below I report the conversion in opendocument format of the text Paragraph containing the text:

oParRef.charStylenames = array (“stylename 1”, “stylename 2”) in the event of a conflict of attributes, the last one applied prevails (here: “stylename 2”)

The formatting of the character styles was then applied to the charStylenames property of the paragraph, assigning them as a value array (“stylename 1”, “stylename 2”)
After saving the file, only references to styles appear in the content.xml in the xml encoding of the paragraph

<text:p text:style-name="P1">
     <text:span text:style-name="stylename 1">
		<text:span text:style-name="stylename 2">
			oParRef.charStylenames=array("stylename 1","stylename 2")
			in the event of a conflict of attributes, the last one applied prevails (here: "stylename 2")
		</text:span>
	</text:span>
</text:p>

Note that only the last applied style appears in the style inspector, while in the UNO object inspector it correctly reports that the charStylenames property of the paragraph contains an array with the names of the two styles

Not an expert comment, but the result of observation on the XML file.

Styles are usually referenced indirectly from <text> element. Paragraph styles are named Px and there is an intermediate table where P1 is associated with Text Body (just an example. Simalarly, character styles are indirectly referenced through a Ty name.

Since you don’t follow the same strategy, your document will not be correctly updated if you rename your character styles, e.g. stylename 1 is renamed stylename b. This is done in the intermediate association table where you change only once the “user name” while the Ty remains in the text. This allows for a very fast name change without any scan of the document. In your text, reference to stylename 1 is kept while you intended to point to stylename b.

If you never intend to rename your styles, you’ll be OK but keep in mind the potential problem. I don’t think it is worth the pain to try to mimic the build behaviour with sophisticated macros (which anyway will be very hard to get correct).

I can be wrong, I am not an opendocument expert, but the technique of using an intermediate table by calling paragraph / character styles with names Px / Ty, it seems to me that it only happens when editing the text of one paragraph / character to handle each subsequent revision.
From tests done in the past it seemed to me that each revision was linked to a different Px (or the same px but with a different rsid, i don’t remember) all linked to the original style
In the case of my file, I have not changed the text of the affected paragraphs, after your post I tried to rename the stilename 1 and after saving the file all the occurrences of the old stilename 1 have been correctly replaced in the content.xml in the new stilename 1

I figured it out. This appends a new style to the existing ones:

charStyleNames = oParSection.charStyleNames
lb = LBound(charStyleNames)
ub = UBound(charStyleNames) + 1
redim preserve charStyleNames(lb to ub)
charStyleNames(ub) = "NewStyle"
oParSection.charStyleNames = charStyleNames
2 Likes