Einfügen eines Kommentars in ein Textverarbeitungsdokument
In diesem Thema wird gezeigt, wie Sie die Klassen im Open XML SDK für Office verwenden, um dem ersten Absatz in einem Textverarbeitungsdokument programmgesteuert einen Kommentar hinzuzufügen.
Öffnen des vorhandenen Dokuments zum Bearbeiten
Um ein vorhandenes Dokument zu öffnen, instanziieren Sie die WordprocessingDocument -Klasse wie in der folgenden using
Anweisung gezeigt. Öffnen Sie in derselben Anweisung die Textverarbeitungsdatei am angegebenen Dateipfad , indem Sie die Open(String, Boolean) -Methode verwenden, wobei der boolesche Parameter auf true
festgelegt ist, um die Bearbeitung im Dokument zu ermöglichen.
using (WordprocessingDocument document = WordprocessingDocument.Open(fileName, true))
Mit v3.0.0 und höher wurde die Close() -Methode entfernt, um sich auf die using-Anweisung zu verlassen.
Dadurch wird sichergestellt, dass die Dispose() -Methode automatisch aufgerufen wird, wenn die schließende Klammer erreicht ist. Der Block, der auf die using-Anweisung folgt, richtet einen Bereich für das Objekt ein, das in der using-Anweisung erstellt oder benannt wird. Da die WordprocessingDocument -Klasse im Open XML SDK das Objekt als Teil der IDisposable Implementierung automatisch speichert und schließt und da Dispose() automatisch aufgerufen wird, wenn Sie den Block beenden, müssen Sie oder Dispose() nicht explizit aufrufenSave(), solange Sie eine using
-Anweisung verwenden.
Funktionsweise des Beispielcodes
Nach dem Öffnen des Dokuments können Sie den ersten Absatz suchen, um einen Kommentar anzufügen. Der Code findet den ersten Absatz, indem die First Erweiterungsmethode für alle nachfolgerfähigen Elemente des Dokumentelements vom Typ Paragraphaufgerufen wird. Die First
-Methode ist ein Member der Enumerable -Klasse. Die System.Linq.Enumerable
-Klasse stellt Erweiterungsmethoden für Objekte bereit, die die IEnumerable<T> -Schnittstelle implementieren.
Paragraph firstParagraph = document.MainDocumentPart.Document.Descendants<Paragraph>().First();
wordprocessingCommentsPart.Comments ??= new Comments();
string id = "0";
Der Code bestimmt zunächst, ob ein WordprocessingCommentsPart Teil vorhanden ist. Rufen Sie dazu die MainDocumentPart generische Methode auf, GetPartsCountOfType
und geben Sie eine Art von an WordprocessingCommentsPart
.
Wenn ein WordprocessingCommentsPart
Teil vorhanden ist, ruft der Code einen neuen Id
Wert für das Objekt ab, den Comment er dem vorhandenen WordprocessingCommentsPart
Comments Auflistungsobjekt hinzufügen wird. Dazu wird der höchste Id
Attributwert gesucht, der Comments
einem Comment
im Auflistungsobjekt zugewiesen ist, den Wert um eins inkrementiert und dann als Id
Wert gespeichert. Wenn kein WordprocessingCommentsPart
Teil vorhanden ist, erstellt der Code einen mit der AddNewPart -Methode des MainDocumentPart -Objekts und fügt diesem dann ein Comments
Auflistungsobjekt hinzu.
if (document.MainDocumentPart.GetPartsOfType<WordprocessingCommentsPart>().Count() > 0)
{
if (wordprocessingCommentsPart.Comments.HasChildren)
{
// Obtain an unused ID.
id = (wordprocessingCommentsPart.Comments.Descendants<Comment>().Select(e =>
{
if (e.Id is not null && e.Id.Value is not null)
{
return int.Parse(e.Id.Value);
}
else
{
throw new ArgumentNullException("Comment id and/or value are null.");
}
})
.Max() + 1).ToString();
}
}
Die Comment
- und Comments
-Objekte stellen kommentar- bzw. comments-Elemente im Open XML-Wordprocessing-Schema dar. Ein Comment
muss einem Comments
-Objekt hinzugefügt werden, damit der Code zuerst ein Comments
-Objekt instanziiert (mit den Zeichenfolgenargumenten author
, initials
und comments
, die an die AddCommentOnFirstParagraph
-Methode übergeben wurden).
Der Kommentar wird durch das folgende WordprocessingML-Codebeispiel dargestellt. .
<w:comment w:id="1" w:initials="User">
...
</w:comment>
Der Code fügt dann den Comment
an das Comments
-Objekt an. Dadurch wird die erforderliche XML-DOM-Struktur (Document Object Model) im Arbeitsspeicher erstellt, die aus einem comments
übergeordneten Element mit comment
untergeordneten Elementen besteht.
Paragraph p = new Paragraph(new Run(new Text(comment)));
Comment cmt =
new Comment()
{
Id = id,
Author = author,
Initials = initials,
Date = DateTime.Now
};
cmt.AppendChild(p);
wordprocessingCommentsPart.Comments.AppendChild(cmt);
Das folgende WordprocessingML-Codebeispiel stellt den Inhalt eines Kommentarteils in einem WordprocessingML-Dokument dar.
<w:comments>
<w:comment … >
…
</w:comment>
</w:comments>
Wenn das Comment
Objekt instanziiert ist, ordnet der Code einem Comment
Bereich im Wordprocessing-Dokument zu.
CommentRangeStart - und CommentRangeEnd -Objekte entsprechen den commentRangeStart
Elementen und commentRangeEnd
im Open XML-Wordprocessing-Schema.
Ein CommentRangeStart
-Objekt wird als Argument für die InsertBefore -Methode des Paragraph -Objekts angegeben, und ein CommentRangeEnd
-Objekt wird an die InsertAfter -Methode übergeben.
Dadurch wird ein Kommentarbereich erstellt, der von unmittelbar vor dem ersten Zeichen des ersten Absatzes im Textverarbeitungsdokument bis unmittelbar nach dem letzten Zeichen des ersten Absatzes reicht.
Ein CommentReference -Objekt stellt ein commentReference
Element im Open XML-Wordprocessing-Schema dar. Ein commentReference verknüpft einen bestimmten Kommentar im WordprocessingCommentsPart
Teil (die Comments.xml-Datei im Wordprocessing-Paket) mit einem bestimmten Speicherort im Dokumenttext (dem Teil, der MainDocumentPart
in der Document.xml-Datei im Wordprocessing-Paket enthalten ist). Das id
Attribut von comment, commentRangeStart, commentRangeEnd und commentReference ist für einen bestimmten Kommentar identisch, sodass das commentReference-Attribut id
mit dem Wert des Kommentarattributes id
übereinstimmen muss, mit dem es verknüpft ist. Im Beispiel fügt der Code mithilfe der API ein commentReference
-Element hinzu, instanziiert ein CommentReference
-Objekt unter Angabe des Id
Werts und fügt es dann einem Run -Objekt hinzu.
firstParagraph.InsertBefore(new CommentRangeStart()
{ Id = id }, firstParagraph.GetFirstChild<Run>());
// Insert the new CommentRangeEnd after last run of paragraph.
var cmtEnd = firstParagraph.InsertAfter(new CommentRangeEnd()
{ Id = id }, firstParagraph.Elements<Run>().Last());
// Compose a run with CommentReference and insert it.
firstParagraph.InsertAfter(new Run(new CommentReference() { Id = id }), cmtEnd);
Beispielcode
Das folgende Codebeispiel zeigt, wie Sie einen Kommentar erstellen und einem Bereich in einem Textverarbeitungsdokument zuordnen. Um die -Methode AddCommentOnFirstParagraph
aufzurufen, übergeben Sie den Pfad des Dokuments, Ihren Namen, Ihre Initialen und den Kommentartext.
string fileName = args[0];
string author = args[1];
string initials = args[2];
string comment = args[3];
AddCommentOnFirstParagraph(fileName, author, initials, comment);
Nachstehend ist der vollständige Beispielcode in C# und Visual Basic aufgeführt.
// Insert a comment on the first paragraph.
static void AddCommentOnFirstParagraph(string fileName, string author, string initials, string comment)
{
// Use the file name and path passed in as an
// argument to open an existing Wordprocessing document.
using (WordprocessingDocument document = WordprocessingDocument.Open(fileName, true))
{
if (document.MainDocumentPart is null)
{
throw new ArgumentNullException("MainDocumentPart and/or Body is null.");
}
WordprocessingCommentsPart wordprocessingCommentsPart = document.MainDocumentPart.WordprocessingCommentsPart ?? document.MainDocumentPart.AddNewPart<WordprocessingCommentsPart>();
// Locate the first paragraph in the document.
Paragraph firstParagraph = document.MainDocumentPart.Document.Descendants<Paragraph>().First();
wordprocessingCommentsPart.Comments ??= new Comments();
string id = "0";
// Verify that the document contains a
// WordProcessingCommentsPart part; if not, add a new one.
if (document.MainDocumentPart.GetPartsOfType<WordprocessingCommentsPart>().Count() > 0)
{
if (wordprocessingCommentsPart.Comments.HasChildren)
{
// Obtain an unused ID.
id = (wordprocessingCommentsPart.Comments.Descendants<Comment>().Select(e =>
{
if (e.Id is not null && e.Id.Value is not null)
{
return int.Parse(e.Id.Value);
}
else
{
throw new ArgumentNullException("Comment id and/or value are null.");
}
})
.Max() + 1).ToString();
}
}
// Compose a new Comment and add it to the Comments part.
Paragraph p = new Paragraph(new Run(new Text(comment)));
Comment cmt =
new Comment()
{
Id = id,
Author = author,
Initials = initials,
Date = DateTime.Now
};
cmt.AppendChild(p);
wordprocessingCommentsPart.Comments.AppendChild(cmt);
// Specify the text range for the Comment.
// Insert the new CommentRangeStart before the first run of paragraph.
firstParagraph.InsertBefore(new CommentRangeStart()
{ Id = id }, firstParagraph.GetFirstChild<Run>());
// Insert the new CommentRangeEnd after last run of paragraph.
var cmtEnd = firstParagraph.InsertAfter(new CommentRangeEnd()
{ Id = id }, firstParagraph.Elements<Run>().Last());
// Compose a run with CommentReference and insert it.
firstParagraph.InsertAfter(new Run(new CommentReference() { Id = id }), cmtEnd);
}
}