2 votes

Comparer les emplacements de texte dans un document Word

Je génère un document Word en remplaçant un texte de remplacement dans le document modèle par mes valeurs. Pour ce faire, j'utilise GemBox.Document, et plus précisément le code suivant Rechercher et remplacer ejemplo:

var document = DocumentModel.Load("input.docx");

var firstPlaceholder = document.Content.Find("%Text1%").First();
firstPlaceholder.LoadText("Value 1");

var secondPlaceholder = document.Content.Find("%Text2%").First();
firstPlaceholder.LoadText("Value 2");

document.Save("output.docx");

Cela fonctionne très bien.

Mais j'ai maintenant un scénario dans lequel les valeurs qui remplaceront les caractères de remplacement dépendent de leur emplacement, plus précisément, si le caractère de remplacement apparaît avant ou après un paragraphe spécifique du document.

J'ai essayé d'utiliser quelque chose comme ceci :

Paragraph separator = ...

string firstPlaceholderText = "%Text1%";
string separatorText = seperator.Content.ToString();
string wholeDocumentText = document.Content.ToString();

if (wholeDocumentText.IndexOf(firstPlaceholderText) < wholeDocumentText.IndexOf(separatorText))
{
    // The placeholder is before the separator...
}
else
{
    // The placeholder is after the separator...
}

Cependant, ce même separatorText peut apparaître à plusieurs endroits dans le document. string.IndexOf() n'est pas une solution viable pour moi.

Existe-t-il un autre moyen d'effectuer cette comparaison ou de déterminer l'emplacement d'un espace réservé par rapport à un autre élément du document ?

2voto

Mario Points 13

Essayez ceci :

static bool IsPositionBefore(ContentPosition position1, ContentPosition position2)
{
    var parentIndexes1 = GetParentIndexes(position1.Parent);
    var parentIndexes2 = GetParentIndexes(position2.Parent);

    int count = Math.Min(parentIndexes1.Count, parentIndexes2.Count);
    for (int i = 0; i < count; i++)
    {
        if (parentIndexes1[i] < parentIndexes2[i])
            return true;

        if (parentIndexes1[i] > parentIndexes2[i])
            return false;
    }

    // Both positions are inside the same parent element.
    var parent = position1.Parent;
    var parentClone = parent.Clone(true);

    string positionMarker1 = "\u0001";
    string positionMarker2 = "\u0002";
    position1.LoadText(positionMarker1);
    position2.LoadText(positionMarker2);

    string parentContent = parent.Content.ToString();
    int positionOffset1 = parentContent.IndexOf(positionMarker1, StringComparison.Ordinal);
    int positionOffset2 = parentContent.IndexOf(positionMarker2, StringComparison.Ordinal);

    parent.Content.Set(parentClone.Content);

    return positionOffset1 < positionOffset2;
}

static IList<int> GetParentIndexes(Element element)
{
    var parentIndexes = new List<int>();

    while (element.Parent != null)
    {
        parentIndexes.Add(element.ParentCollection.IndexOf(element));
        element = element.Parent;
    }

    parentIndexes.Reverse();

    return parentIndexes;
}

Voici également comment vous pouvez l'utiliser IsPositionBefore méthode :

if (IsPositionBefore(firstPlaceholder.Start, separator.Content.Start))
{
    // The placeholder is before the separator...
}
else
{
    // The placeholder is after the separator...
}

La partie la plus délicate est de savoir comment déterminer la position qui vient en premier lorsque les deux positions se trouvent à l'intérieur du même élément.

En effet, le ContentPosition n'a pas actuellement d'API de décalage qui vous indiquerait l'endroit exact où il se trouve dans l'élément.

Ce que je fais donc, c'est ajouter temporairement deux caractères de contrôle aléatoires, vérifier lequel apparaît avant l'autre, puis les supprimer.

Je pense que cette approche est sûre car les documents Word ne peuvent pas contenir de caractères de contrôle (les applications Word les considèrent comme corrompus) et si vous essayez d'enregistrer un document de type DocumentModel qui contient de tels caractères, vous obtiendrez une exception.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X