Hallo Meina,
Post by Meina MeistWenn ich den Text an der Textmarke geändert habe, dann ist die Textmarke
weg - einfach nicht mehr definiert.
Das ist so bei Design:
"Bookmarks provide you a way to name and keep track of a particular
Range. The user can even edit the Range and the modified Range will
still be accessible by it's name *unless the user completely deletes the
Range*. [...] For example, setting the Text property of the Range
associated with a bookmark replaces the Range and in the process deletes
the bookmark associated with the Range." (Zitat aus "Visual Studio Tools
for Office", ISBN 0-321-33488-4)
Wenn du allerdings VSTO 2.0 verwendest und dich dessen Bookmark
Host-Control bedienst statt dem Bookmark Objekt aus der PIA (das VSTO
Bookmark aggregiert das PIA Objekt), ist sichergestellt, dass beim
Setzen der Text-Property die Textmarke nicht gelöscht wird.
Post by Meina MeistDa die Textmarke nicht mehr da ist, kann auch die Referenz auf die Textmarke
nicht aktualisiert werden und ich erhalte stattdessen einen Fehlertext im
Dokument.
Ggf. mit b.Name den Namen der Textmarke auslesen und b.Start sowie
b.Start + myText.Lenght als Start und Ende merken und nach dem Zuweisen
des Textes die Textmarke einfach neu erstellen. Hier ein kleines
Beispiel. Dazu brauchst du nur ein Worddokument mit einigen Bookmarks
drin. Zunächst einmal werden ein paar Hilfvariablen angelegt die wir
brauchen und das Dokument geöffnet:
object docFile = args[0]; // enthält den Dateipfad
object missing = Type.Missing;
Dictionary<string, Word.Bookmark> newBookmarks = new Dictionary<string,
Word.Bookmark>(); // hier speichern wir die neu anzulegenden Textmarken
zwischen, und zwar den Namen und Range.
int i = 0; // die nte Textmarke
string bmText = "Dies ist die {0}. Textmarke (Name: '{1}') im
Dokument."; // Der Formatstring den wir als neuen Text einfügen wollen
Word.Application app = new Word.Application();
Word.Document doc = app.Documents.Open(ref docFile,
ref missing, ref missing, ref missing, ref
missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref
missing, ref missing, ref missing, ref missing,
ref missing);
// missing = brauchen wir alles nicht, müssen es aber mit angeben.
Dann durlaufen wir in einer Schleife alle Textmarken, ändern ihren Text
und merken uns ihren Namen und neuen Range:
foreach (Word.Bookmark bm in doc.Bookmarks)
{
try
{
string neuerBmText = string.Format(bmText, i, bm.Name);
object start = bm.Range.Start; // Anfang der Textmarke
object end = (int)start + neuerBmText.Length;
// neues Ende
string name = bm.Name;
bm.Range.Text = neuerBmText;
// Wir überschreiben den Inhalt der Textmarke
// (und löschen sie damit)
newBookmarks.Add(name,
(Word.Bookmark) doc.Range(ref start, ref end));
// merken sie uns aber...
} catch(Exception ex)
{
// zur Sicherheit mit Fehlerbehandlung
Console.WriteLine(ex);
}
}
Würden wir die neuen Textmarken gleich erzeugen, würden wir auch die
Ergebnismenge der foreach-Schleife jedes mal ändern und so in eine
Endlosschleife gelangen. Deshalb haben wir uns die neu zu erstellenden
Textmarken in einer lokalen Liste gemerkt und erstellen sie jetzt:
foreach (KeyValuePair<string, Word.Bookmark> bm in newBookmarks)
{
try
{
if (!doc.Bookmarks.Exists(bm.Key))
{
// Zur Sicherheit prüfen wir noch mal,
// dass die Textmarke wirklich nicht existiert.
object range = bm.Value;
doc.Bookmarks.Add(bm.Key, ref range);
}
}
catch (Exception ex)
{
// und auch hier wieder mit Fehlerbehandlung,
// wir arbeiten schließlich mit COM!!!
Console.WriteLine(ex);
}
}
newBookmarks.Clear(); // nicht vergessen, die Referenzen auf die
COM-Objekte (Ranges) wieder freizugeben!
Anschließend noch das Dokument speichern und Word beenden:
doc.Save();
doc = null;
app.Quit(ref missing, ref missing, ref missing);
app = null;
Und ganz wichtig, alle auf COM-Objekte erstellten Referenzen löschen,
weil COM mit einem Referenzzähler arbeitet und die Objekte erst aus dem
Speicher entfernt, wenn deren Zähler auf 0 zurückgesetzt werden. Sonst
dürfte Word im Speicher verbleiben, was wir ja nicht wollen. Und wenn
das Programm auf einem Server sagen wir mal stündlich im Hintergrund
läuft, hätten wir nach einem Tag 24 Word-Leichen im Speicher und der
wird dann auch irgendwann knapp.
Ich hoffe, dir damit etwas geholfen zu haben.
Viele Grüße und ein schönes Wochenende noch.
Marco
PS: Falls du noch Fragen haben solltest, melde dich bitte bis Dienstag
nachmittag, danach bin ich ca. 2 Wochen nicht online.