Appliquer un style à un paragraphe dans un document de traitement de texte
Cette rubrique montre comment utiliser les classes du Kit de développement logiciel (SDK) Open XML pour Office afin d’appliquer par programmation un style à un paragraphe dans un document de traitement de texte. Elle contient un exemple de méthode ApplyStyleToParagraph pour illustrer cette tâche, ainsi que plusieurs exemples de méthodes supplémentaires pour vérifier si un style existe, ajouter un nouveau style, ainsi que le composant de styles.
Méthode ApplyStyleToParagraph
L'exemple de méthode ApplyStyleToParagraph permet d'appliquer un style à un paragraphe. Vous devez d'abord obtenir une référence pointant vers le document, ainsi qu'une référence pointant vers le paragraphe auquel vous souhaitez appliquer le style. La méthode accepte 4 paramètres indiquant : la référence du document Word ouvert, le styleid du style à appliquer, le nom du style à appliquer et la référence du paragraphe auquel vous voulez appliquer le style.
public static void ApplyStyleToParagraph(WordprocessingDocument doc, string styleid, string stylename, Paragraph p)
Les sections suivantes de cette rubrique décrivent l'implémentation de cette méthode, ainsi que son code de prise en charge et la manière de l'appeler. La liste complète de cet exemple de code est disponible dans la section Exemple de code, à la fin de cette rubrique.
Obtenir un objet WordprocessingDocument
La section Exemple de code indique également le code requis à configurer pour appeler l'exemple de méthode. Pour utiliser cette méthode pour appliquer un style à un paragraphe dans un document, vous devez tout d'abord utiliser une référence pointant vers le document ouvert. Dans le kit de développement Open XML, la classe WordprocessingDocument représente un package de documents Word. Pour ouvrir et utiliser un document Word, créez une instance de la classe WordprocessingDocument à partir du document. Après avoir créé le instance, utilisez-le pour obtenir l’accès au composant de document main qui contient le texte du document. Le contenu de la partie principale du document est représenté dans le package au format XML à l'aide de marques de révision WordprocessingML.
Pour créer la classe instance, appelez l’une des surcharges de la méthode Open(). L’exemple de code suivant montre comment utiliser la surcharge de l’élément WordprocessingDocument.Open. Le premier paramètre accepte une chaîne qui représente le chemin d’accès complet du document à ouvrir. Le deuxième paramètre prend une valeur de true ou false et indique s'il faut ouvrir le fichier pour modification. Dans cet exemple, le paramètre est true, car le document est ouvert en lecture seule.
using (WordprocessingDocument doc =
WordprocessingDocument.Open(fileName, true))
{
// Code removed here.
}
Structure d’un document WordProcessingML
La structure de base d’un document WordProcessingML se compose des éléments document et body , suivis d’un ou plusieurs éléments de niveau bloc tels que p, qui représente un paragraphe. Un paragraphe contient un ou plusieurs éléments r. Le r signifie « run » (exécution), qui est une zone de texte avec un ensemble de propriétés courant, comme par exemple la mise en forme. Une exécution contient un ou plusieurs éléments t. L'élément t contient une plage de texte. L’exemple de code suivant montre le balisage WordprocessingML pour un document qui contient le texte « Exemple de texte ».
<w:document xmlns:w="https://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>Example text.</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
À l’aide du Kit de développement logiciel (SDK) Open XML, vous pouvez créer une structure de document et du contenu à l’aide de classes fortement typées qui correspondent à des éléments WordprocessingML . Vous trouverez ces classes dans l'espace de noms DocumentFormat.OpenXml.Wordprocessing . Le tableau suivant répertorie les noms des classes qui correspondent aux éléments document, body, p, r et t.
Élément WordprocessingML | Classe du Kit de développement logiciel (SDK) Open XML | Description |
---|---|---|
document | Document | Élément racine de la partie principale du document. |
body | Body | Conteneur des structures de niveau bloc, telles que paragraphs, tables, annotations et autres structures décrites dans la spécification ISO/IEC 29500. |
p | Paragraph | Paragraphe. |
r | Run | Exécution. |
t | Text | Plage de texte. |
Pour plus d’informations sur la structure globale des parties et éléments d’un document WordprocessingML, consultez Structure d’un document WordprocessingML.
Obtenir le paragraphe à appliquer au style
Après avoir ouvert le fichier, l'exemple de code récupère une référence pointant vers le premier paragraphe. Comme un corps de document de traitement de texte classique contient de nombreux types d'élément, le code filtre les descendants du corps du document par type Paragraph. La méthode ElementAtOrDefault est alors utilisée pour récupérer une référence pointant vers le paragraphe. Comme les éléments sont indexés en commençant à zéro, vous transmettez un zéro pour extraire la référence pointant vers le premier paragraphe, comme montré dans l'exemple suivant.
// Get the first paragraph.
Paragraph p =
doc.MainDocumentPart.Document.Body.Descendants<Paragraph>()
.ElementAtOrDefault(0);
// Check for a null reference.
if (p == null)
{
// Code removed here…
}
La référence pointant vers le paragraphe trouvé est stockée dans une variable nommée p. Si elle ne trouve pas de paragraphe pour l'index spécifié, la méthode ElementAtOrDefault renvoie la valeur null comme valeur par défaut. Cela permet de tester les valeurs null et de générer une erreur accompagnée d'un message adéquat.
Lorsque vous avez les références pointant vers le document et le paragraphe, vous pouvez appeler l'exemple de méthode ApplyStyleToParagraph pour continuer le travail. Pour appeler la méthode, vous devez transférer la référence au document comme premier paramètre, le styleid du style à appliquer comme deuxième paramètre, le nom du style comme troisième paramètre et la référence pointant vers le paragraphe auquel vous voulez appliquer le style comme quatrième paramètre.
Ajouter l’élément de propriétés de paragraphe
La première étape de l'exemple de méthode consiste à vérifier que le paragraphe possède un élément de propriétés de paragraphe. L'élément de propriétés de paragraphe est un élément enfant du paragraphe et inclut un ensemble de propriétés qui vous permettent de spécifier la mise en forme du paragraphe.
Les informations suivantes provenant de la spécification ISO/IEC 29500 présentent l'élément pPr (propriétés de paragraphe) utilisé pour spécifier la mise en forme d'un paragraphe. Notez que les numéros de section précédés du signe § proviennent de la spécification ISO.
Dans le paragraphe, toutes les mises en forme enrichies au niveau du paragraphe sont stockées dans l’élément pPr (§17.3.1.25 ; §17.3.1.26). [Remarque : Quelques exemples de propriétés de paragraphe sont l’alignement, la bordure, le remplacement de coupure d’union, la mise en retrait, l’espacement des lignes, l’ombrage, l’orientation du texte et le contrôle veuve/orphelin.
L'élément pStyle, qui permet de spécifier le style à appliquer au paragraphe, se trouve parmi ces propriétés. Par exemple, l'exemple de balisage suivant présente un élément pStyle qui spécifie le style « OverdueAmount ».
<w:p xmlns:w="https://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:pPr>
<w:pStyle w:val="OverdueAmount" />
</w:pPr>
...
</w:p>
Dans le kit de développement logiciel Open XML, l’élément pPr est représenté par la classe ParagraphProperties. Le code détermine si l’élément existe. Si ce n’est pas le cas, il crée une instance de la classe ParagraphProperties. L’élément pPr est un enfant de l’élément p (paragraphe) ; par conséquent, la méthode PrependChild<T>(T) est utilisée pour ajouter l’instance, comme illustré dans l’exemple suivant.
// If the paragraph has no ParagraphProperties object, create one.
if (p.Elements<ParagraphProperties>().Count() == 0)
{
p.PrependChild<ParagraphProperties>(new ParagraphProperties());
}
// Get the paragraph properties element of the paragraph.
ParagraphProperties pPr = p.Elements<ParagraphProperties>().First();
Ajouter le composant Styles
Une fois le paragraphe trouvé et l’élément de propriétés de paragraphe présent, vérifiez maintenant que les conditions préalables sont en place pour appliquer le style. Les styles dans WordprocessingML sont stockés dans leur propre partie unique. Même s’il est généralement vrai que le composant ainsi qu’un ensemble de styles de base sont créés automatiquement lorsque vous créez le document à l’aide d’une application telle que Microsoft Word, le composant styles n’est pas nécessaire pour qu’un document soit considéré comme valide. Si vous créez le document par programmation à l’aide du Kit de développement logiciel (SDK) Open XML, la partie styles n’est pas créée automatiquement ; vous devez le créer explicitement. Par conséquent, le code suivant vérifie que la partie styles existe et la crée si ce n’est pas le cas.
// Get the Styles part for this document.
StyleDefinitionsPart part =
doc.MainDocumentPart.StyleDefinitionsPart;
// If the Styles part does not exist, add it and then add the style.
if (part == null)
{
part = AddStylesPartToPackage(doc);
// Code removed here...
}
L'exemple de méthode AddStylesPartToPackage ajoute le composant de styles. Il crée une partie du type StyleDefinitionsPart, puis l'ajoute comme enfant au composant du document principal. Le code modifie ensuite l’élément racine Styles, qui est l’élément parent contenant tous les styles. L’élément Styles est représenté par la classe Styles dans le kit de développement logiciel Open XML. Enfin, le code enregistre le composant. Enfin, le code enregistre le composant.
// Add a StylesDefinitionsPart to the document. Returns a reference to it.
public static StyleDefinitionsPart AddStylesPartToPackage(WordprocessingDocument doc)
{
StyleDefinitionsPart part;
part = doc.MainDocumentPart.AddNewPart<StyleDefinitionsPart>();
Styles root = new Styles();
root.Save(part);
return part;
}
Vérifier que le style existe
L’application d’un style qui n’existe pas à un paragraphe n’a aucun effet ; aucune exception n’est générée et aucune modification de mise en forme ne se produit. L’exemple de code vérifie que le style existe avant de tenter d’appliquer le style. Les styles sont stockés dans la partie styles. Par conséquent, si la partie styles n’existe pas, le style lui-même ne peut pas exister.
Si le composant de styles existe, le code vérifie un style correspondant en appelant l'exemple de méthode IsStyleIdInDocument, puis en transmettant le document et le styleid. Si le code ne trouve pas de correspondance dans le styleid, il tente de rechercher le styleid en appelant l'exemple de méthode GetStyleIdFromStyleName, puis lui transmet le nom du style.
Si le style n'existe pas (parce que le composant de styles n'existe pas ou parce qu'il existe, mais pas le style), le code appelle l'exemple de méthode AddNewStyle pour ajouter le style.
// Get the Styles part for this document.
StyleDefinitionsPart part =
doc.MainDocumentPart.StyleDefinitionsPart;
// If the Styles part does not exist, add it and then add the style.
if (part == null)
{
part = AddStylesPartToPackage(doc);
AddNewStyle(part, styleid, stylename);
}
else
{
// If the style is not in the document, add it.
if (IsStyleIdInDocument(doc, styleid) != true)
{
// No match on styleid, so let's try style name.
string styleidFromName = GetStyleIdFromStyleName(doc, stylename);
if (styleidFromName == null)
{
AddNewStyle(part, styleid, stylename);
}
else
styleid = styleidFromName;
}
}
Dans l’exemple de méthode IsStyleInDocument, le travail commence par la récupération de l’élément Styles par le biais de la propriété Styles de l’élément StyleDefinitionsPart du document principal, puis par la détermination de l’existence d’un style enfant de cet élément. Tous les éléments de style sont stockés en tant qu’enfants de l’élément de styles.
Si des styles existent, le code recherche une correspondance sur le styleid. Le styleid est un attribut du style qui est utilisé à de nombreux endroits dans le document pour faire référence au style et peut être considéré comme son identificateur principal. En règle générale, le styleid permet d'identifier un style dans le code. La méthode FirstOrDefault prend par défaut la valeur null si aucune correspondance n’est trouvée. Le code vérifie donc la valeur null pour voir si un style a été mis en correspondance, comme illustré dans l’extrait suivant.
// Return true if the style id is in the document, false otherwise.
public static bool IsStyleIdInDocument(WordprocessingDocument doc,
string styleid)
{
// Get access to the Styles element for this document.
Styles s = doc.MainDocumentPart.StyleDefinitionsPart.Styles;
// Check that there are styles and how many.
int n = s.Elements<Style>().Count();
if (n==0)
return false;
// Look for a match on styleid.
Style style = s.Elements<Style>()
.Where(st => (st.StyleId == styleid) && (st.Type == StyleValues.Paragraph))
.FirstOrDefault();
if (style == null)
return false;
return true;
}
S'il ne trouve pas le style via le styleid, le code tente alors de trouver une correspondance au moyen du nom du style. L'exemple de méthode GetStyleIdFromStyleName effectue ce travail, en recherchant une correspondance via le nom du style, puis en renvoyant le styleid de l'élément correspondant en cas de résultat, ou la valeur null en l'absence de résultat.
Ajouter le style à la partie styles
L'exemple de méthode AddNewStyle récupère trois paramètres. Le premier paramètre récupère une référence pointant vers le composant de styles. Le deuxième paramètre récupère le styleid du style et le troisième paramètre, le nom du style. Le code AddNewStyle crée la définition du style nommé au sein du composant spécifié.
Pour créer le style, le code instancie la classe Style et définit certaines propriétés, telles que l’élément Type du style (paragraphe) et l’élément StyleId. Comme mentionné ci-dessus, l’élément styleid est utilisé par le document pour établir une référence pointant vers le style et peut être considéré comme son identificateur principal. En règle générale, le styleid permet d'identifier un style dans le code. Un style peut également porter un nom de style convivial distinct, affiché dans l'interface utilisateur. Généralement, le nom du style apparaît donc avec une majuscule et un espacement (par exemple, Titre 1), tandis que le styleid est plus concis (par exemple, titre1), car destiné à un usage interne. Dans le code suivant, le styleid et le nom du style récupèrent leurs valeurs à partir des paramètres styleid et stylename.
L'étape suivante consiste à spécifier plusieurs propriétés supplémentaires, telles que le style sur lequel repose le nouveau style et le style à appliquer automatiquement au paragraphe suivant. Le code spécifie ces deux éléments en tant que style « Normal ». N'oubliez pas que la valeur à spécifier ici est le styleid du style normal. Le code ajoute ces propriétés en tant qu'enfants de l'élément de style.
Lorsque le code a terminé l'instanciation du style et configuré les propriétés de base, vous pouvez passer à la mise en forme du style. Celle-ci est effectuée dans les propriétés du paragraphe (pPr) et exécute les éléments des propriétés (rPr). Pour définir les caractéristiques et la couleur de la police à appliquer dans un paragraphe, vous utilisez les propriétés d'exécution.
Pour créer l’élément rPr avec les éléments enfants appropriés, le code crée une instance de la classe StyleRunProperties, puis ajoute les instances des classes de propriété appropriées. Pour cet exemple de code, le style spécifie la police Lucida Console, une taille 12, un affichage en gras et en italique, en utilisant la couleur Accent2 du composant de thème du document. La taille est spécifiée en demi-points. Une valeur de 24 équivaut donc à 12 points.
Lorsqu'il termine la définition du style, le code ajoute le style à l'élément de styles du composant de styles, comme illustré dans l'exemple suivant.
// Create a new style with the specified styleid and stylename and add it to the specified
// style definitions part.
private static void AddNewStyle(StyleDefinitionsPart styleDefinitionsPart,
string styleid, string stylename)
{
// Get access to the root element of the styles part.
Styles styles = styleDefinitionsPart.Styles;
// Create a new paragraph style and specify some of the properties.
Style style = new Style() { Type = StyleValues.Paragraph,
StyleId = styleid,
CustomStyle = true };
StyleName styleName1 = new StyleName() { Val = stylename };
BasedOn basedOn1 = new BasedOn() { Val = "Normal" };
NextParagraphStyle nextParagraphStyle1 = new NextParagraphStyle() { Val = "Normal" };
style.Append(styleName1);
style.Append(basedOn1);
style.Append(nextParagraphStyle1);
// Create the StyleRunProperties object and specify some of the run properties.
StyleRunProperties styleRunProperties1 = new StyleRunProperties();
Bold bold1 = new Bold();
Color color1 = new Color() { ThemeColor = ThemeColorValues.Accent2 };
RunFonts font1 = new RunFonts() { Ascii = "Lucida Console" };
Italic italic1 = new Italic();
// Specify a 12 point size.
FontSize fontSize1 = new FontSize() { Val = "24" };
styleRunProperties1.Append(bold1);
styleRunProperties1.Append(color1);
styleRunProperties1.Append(font1);
styleRunProperties1.Append(fontSize1);
styleRunProperties1.Append(italic1);
// Add the run properties to the style.
style.Append(styleRunProperties1);
// Add the style to the styles part.
styles.Append(style);
}
Appliquer le style au paragraphe
À présent, l'exemple de code a localisé le paragraphe, ajouté l'élément de propriétés du paragraphe requis si nécessaire, vérifié la présence du composant de styles et l'a ajouté si nécessaire, ainsi que la présence du style et l'a ajouté si nécessaire. Il vous suffit maintenant de définir le style du paragraphe. Pour effectuer cette tâche, le code crée une instance de la classe ParagraphStyleId avec le styleid, puis place une référence pointant vers cette instance dans la propriété ParagraphStyleId de l'objet de propriétés de paragraphe. Cette action crée et affecte la valeur appropriée à l'élément pStyle qui spécifie le style à utiliser pour le paragraphe.
// Set the style of the paragraph.
pPr.ParagraphStyleId = new ParagraphStyleId(){Val = styleid};
Exemple de code
Vous pouvez utiliser l'exemple de méthode ApplyStyleToParagraph pour appliquer un style nommé à un paragraphe dans un document de traitement de texte à l'aide du Kit de développement logiciel (SDK) Open XML. Le code suivant montre comment ouvrir et acquérir une référence pointant vers un document de traitement de texte et récupérer une référence pointant vers le premier paragraphe, puis appeler la méthode ApplyStyleToParagraph.
Pour appeler la méthode, transférez la référence pointant vers le document en tant que premier paramètre, le styleid du style à appliquer en tant que deuxième paramètre, le nom du style en tant que troisième paramètre et la référence pointant vers le paragraphe auquel vous voulez appliquer le style en tant que quatrième paramètre. Par exemple, le code suivant applique le style « Overdue Amount » au premier paragraphe dans l'exemple de fichier nommé ApplyStyleToParagraph.docx.
string filename = @"C:\Users\Public\Documents\ApplyStyleToParagraph.docx";
using (WordprocessingDocument doc =
WordprocessingDocument.Open(filename, true))
{
// Get the first paragraph.
Paragraph p =
doc.MainDocumentPart.Document.Body.Descendants<Paragraph>()
.ElementAtOrDefault(1);
// Check for a null reference.
if (p == null)
{
throw new ArgumentOutOfRangeException("p",
"Paragraph was not found.");
}
ApplyStyleToParagraph(doc, "OverdueAmount", "Overdue Amount", p);
}
Voici un exemple de code complet en C# et Visual Basic.
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Linq;
// Apply a style to a paragraph.
static void ApplyStyleToParagraph(WordprocessingDocument doc, string styleid, string stylename, Paragraph p)
{
if (doc is null)
{
throw new ArgumentNullException(nameof(doc));
}
// If the paragraph has no ParagraphProperties object, create one.
if (p.Elements<ParagraphProperties>().Count() == 0)
{
p.PrependChild<ParagraphProperties>(new ParagraphProperties());
}
// Get the paragraph properties element of the paragraph.
ParagraphProperties pPr = p.Elements<ParagraphProperties>().First();
// Get the Styles part for this document.
StyleDefinitionsPart? part = doc.MainDocumentPart?.StyleDefinitionsPart;
// If the Styles part does not exist, add it and then add the style.
if (part is null)
{
part = AddStylesPartToPackage(doc);
AddNewStyle(part, styleid, stylename);
}
else
{
// If the style is not in the document, add it.
if (IsStyleIdInDocument(doc, styleid) != true)
{
// No match on styleid, so let's try style name.
string? styleidFromName = GetStyleIdFromStyleName(doc, stylename);
if (styleidFromName is null)
{
AddNewStyle(part, styleid, stylename);
}
else
styleid = styleidFromName;
}
}
// Set the style of the paragraph.
pPr.ParagraphStyleId = new ParagraphStyleId() { Val = styleid };
}
// Return true if the style id is in the document, false otherwise.
static bool IsStyleIdInDocument(WordprocessingDocument doc, string styleid)
{
// Get access to the Styles element for this document.
Styles? s = doc.MainDocumentPart?.StyleDefinitionsPart?.Styles;
if (s is null)
{
return false;
}
// Check that there are styles and how many.
int n = s.Elements<Style>().Count();
if (n == 0)
{
return false;
}
// Look for a match on styleid.
Style? style = s.Elements<Style>()
.Where(st => (st.StyleId is not null && st.StyleId == styleid) && (st.Type is not null && st.Type == StyleValues.Paragraph))
.FirstOrDefault();
if (style is null)
{
return false;
}
return true;
}
// Return styleid that matches the styleName, or null when there's no match.
static string? GetStyleIdFromStyleName(WordprocessingDocument doc, string styleName)
{
StyleDefinitionsPart? stylePart = doc.MainDocumentPart?.StyleDefinitionsPart;
string? styleId = stylePart?.Styles?.Descendants<StyleName>()
.Where(s =>
{
OpenXmlElement? p = s.Parent;
EnumValue<StyleValues>? styleValue = p is null ? null : ((Style)p).Type;
return s.Val is not null && s.Val.Value is not null && s.Val.Value.Equals(styleName) &&
(styleValue is not null && styleValue == StyleValues.Paragraph);
})
.Select(n =>
{
OpenXmlElement? p = n.Parent;
return p is null ? null : ((Style)p).StyleId;
}).FirstOrDefault();
return styleId;
}
// Create a new style with the specified styleid and stylename and add it to the specified
// style definitions part.
static void AddNewStyle(StyleDefinitionsPart styleDefinitionsPart, string styleid, string stylename)
{
// Get access to the root element of the styles part.
styleDefinitionsPart.Styles ??= new Styles();
Styles styles = styleDefinitionsPart.Styles;
// Create a new paragraph style and specify some of the properties.
Style style = new Style()
{
Type = StyleValues.Paragraph,
StyleId = styleid,
CustomStyle = true
};
StyleName styleName1 = new StyleName() { Val = stylename };
BasedOn basedOn1 = new BasedOn() { Val = "Normal" };
NextParagraphStyle nextParagraphStyle1 = new NextParagraphStyle() { Val = "Normal" };
style.Append(styleName1);
style.Append(basedOn1);
style.Append(nextParagraphStyle1);
// Create the StyleRunProperties object and specify some of the run properties.
StyleRunProperties styleRunProperties1 = new StyleRunProperties();
Bold bold1 = new Bold();
Color color1 = new Color() { ThemeColor = ThemeColorValues.Accent2 };
RunFonts font1 = new RunFonts() { Ascii = "Lucida Console" };
Italic italic1 = new Italic();
// Specify a 12 point size.
FontSize fontSize1 = new FontSize() { Val = "24" };
styleRunProperties1.Append(bold1);
styleRunProperties1.Append(color1);
styleRunProperties1.Append(font1);
styleRunProperties1.Append(fontSize1);
styleRunProperties1.Append(italic1);
// Add the run properties to the style.
style.Append(styleRunProperties1);
// Add the style to the styles part.
styles.Append(style);
}
// Add a StylesDefinitionsPart to the document. Returns a reference to it.
static StyleDefinitionsPart AddStylesPartToPackage(WordprocessingDocument doc)
{
MainDocumentPart mainDocumentPart = doc.MainDocumentPart ?? doc.AddMainDocumentPart();
StyleDefinitionsPart part = mainDocumentPart.AddNewPart<StyleDefinitionsPart>();
Styles root = new Styles();
root.Save(part);
return part;
}