C# Word Dokument bearbeiten.

roker002

Commander
Registriert
Dez. 2007
Beiträge
2.075
Ich versuche gerade an einem Word Dokument zu basteln. Klappt soweit alles, wenn man die richtige Verweise hinzufügt (Achtung keine COM Bibliotheken, war mein Fehler am Anfang).

Also mein Problem ist... ich will eine Fußzeile aufmotzen. Ich bin schon dahintergekommen wie man eine hinzufügt. Word 2007 kann z.B. Seitenende Machen, was einfach besser wirkt. Wie kann ich den mit dem C# Code das erreichen.


Code:
            myword = new Application();
            
            Doc = myword.Documents.Add([COLOR="red"]ref missing[/COLOR], ref missing, ref missing, ref missing);

            Range rng = Doc.Range(ref Start, ref End);


            try
            {
                rng.Font.Name = "Times New Roman";
                rng.Font.Size = 12;
                object filename = "C:\\Users\\User\\Desktop\\test";
                Doc.SaveAs(ref filename, 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);
                this.WriteHead();

                foreach (Section s in Doc.Sections)
                {
                    s.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary].PageNumbers.Add(WdPageNumberAlignment.wdAlignPageNumberRight, missing);
                    s.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary].PageNumbers.IncludeChapterNumber = true;
                    s.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary].PageNumbers.NumberStyle = WdPageNumberStyle.wdPageNumberStyleUppercaseRoman;

                    //s.Footers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range.Borders[WdBorderType.wdBorderTop].Visible = true;
                }
                Doc.Save();
                myword.Visible = true;

Habe das im Word rot markiert.

Numberstyle hat aber nicht alle diese Elemente zur Auswahl wie im Word selbst.

Hat jemand eine Idee wie man alle Styles herausbekommt?



EDIT

Hier kommt die Auflösung des Problems. Ich bin anders vorgegangen.
Anstatt oben jetzt rot gekennzeichnet beim erstellen eines Dokuments über myword.Documents.Add, füge ich einen Template ein, was vorher missing war. Dieser Template hat schon die notwendigen Informationen zur Vorformatierung des Textes, sowie Vorformatierung des Footers. Somit muss ich nur den Template Lade und die Daten dann aufs Word Dokument übertragen.
 

Anhänge

  • Unbenannt.png
    Unbenannt.png
    91,2 KB · Aufrufe: 877
Zuletzt bearbeitet:
Was mir immer wieder geholfen hatte, war der Macro-Recorder von Word selbst. D.h. Ich hatte irgend eine Aktion im Word zu automatisieren. Hab da einfach den Recorder benutzt und die Aktionen von Hand im Word durchgeführt. Danach habe ich den Quellcode des Macros angeschaut und wusste welche Konstanten, Funktionen etc. verwendet wurden. Die gleichen Konstanten, Funktionen usw. findest du dann in der Typelibrary bzw. in der Interop im Namespace von Word und kannst diese in deinem C# Code verwenden. Sicher hat man am Anfang Schwierigkeiten von VBA auf C# zu wechseln, jedoch ist das auch nur eine Frage der Übung. Syntax ändert sich, aber es bleibt doch die selbe Sosse...

Ansonsten wäre noch die VBA Hilfe für Word eine gute Anlaufstelle zur weiteren Recherche.
 
Ich habe jetzt eine ganz andere Frage... Wenn ich ein Wort markieren will, und dieses dann bearbeiten will, wie kann ich das tun? Ich kenne das mit Range, da kann man vor der Range irgendwas hinzufügen oder danach. Dieses Range lässt sich bearbeiten und Style ändern. Wenn ich ein Wort aus einem Range markieren will, dann habe ich keine Chance!
 
Mit Range bist du schon am richtigen Objekt. Es gibt zwar noch das Selection Objekt, jedoch ist das für die Automatisierung nicht gerade geeignet, da es gegenüber des Range Objektes den ganzen Klumbatsch, wie bei Eingabe von einem User, mit ausführt. Mit anderen Worten, bei großen Aktionen wirds extrem langsam.

Das Range Objekt hat eine Eigenschaft namens Value oder Text. Diese Eigenschaft kannst du auslesen, d.h. du bekommst den enthaltenen Text als String geliefert. Du kannst diese Eigenschaft auch mit deinem eigenen String setzen. Dann wird der Text im Range überschrieben. Schau mal nach den beiden Namen in der Intellisense. Im übrigen bleibt die Formatierung bestehen, es sei denn das Range Objekt umschließt größeren Text mit unterschiedlichen Formatierungen. Dann richtet es sich nach dem ersten Zeichen im Range.

Viel Erfolg.
Rossibaer
 
Vielleicht wäre es für dich noch eine Möglichkeit anstatt mit der API zu arbeiten, das OpenOffice Xml zu nutzen. Dort werden dir direkt Klassen und Funktionen für solche Aktionen angeboten und du quälst dich nicht mit der API. Zumal das SDK auch schmaler ist und du auch auf Server wo kein Office installierst ist Word-Dokumente erstellen kannst(ich weiß ihr fragt euch jetzt was das bringen soll, aber stelle man sich doch einfach einen Reportserver oder sowas vor der erstellte Office-Dokumente per Email an User verschicken soll).
 
hmm open office SDK... ist auch eine gute Überlegung. ich suche diese mal raus.

@range
Ja ich kenne schon Range. Das blöde ist, ich kann kein Range anhand eines Worts bestimmen. Die Enums bringen auch nichts... wenn man Range auswähl. habe schon versucht.
 
@toeffi:
Und da wäre noch zu erwähnen, dass das Format *.odt von OpenOffice nix weiter als eine gezippte Containerdatei ist, die ein paar XML Dateien enthält. Würde mal vermuten das man diese einfach entpackt, dann auf der XML Datei rumrödelt (Klassen für XML lesen und schreiben gibts im .Net reichlich) dann wieder packt und fertig. Da sollte man kein SDK brauchen und muss auch sonst nix weiter großartiges installieren. Aber korrigiere mich bitte wenn ich falsch liege.

@roker:
In der Word API hast du auch eine Find Klasse die über eine Property vom Range Objekt verfügbar ist. Mit der kannst du einfach das Doc durchsuchen und bei einem Treffer ist das Range dann entsprechend auf Position und Länge des Treffers eingestellt. Aber das sind jetzt Sachen die ich mal vor Jahren gemacht habe und seitdem nie wieder ändern musste, weils so gut läuft. Ich schau mal morgen wie das genau geht (habe z.H. kein MS Office installiert). Wenn du jedoch auf dem neumodigen docx Format arbeiten willst, dann gilt gleiches wie bei OpenOffice, d.h. gezippte Datei entpacken auf der entsprechenden xml Datei rumwerkeln und wieder einpacken.
 
@rossibär: Nee das ist richtig. Ja klar, man könnte auch einfach so die Xml datei per Reader/Linq to Xml bearbeiten und so, wenn man das genau Format kennt, für alles weitere nimmste halt einfach das SDK mit dern fertigen klassen. Wobei ich ehrlich sagen muss, das das SDK etwas schwerfällig ist, und man sich erstmal reinfuchsen muss, aber dann ist ganz ok.
 
@toeffi: Ich muss da bald selber mal ran und nen Reporter für OpenOffice schreiben. Habe deswegen schonmal recherchiert und entsprechend auch mich für diesen Lösungsansatz entschieden. Das Ganze deswegen weil ich mit "OpenOffice SDK sucks" bei Google zu viele Treffer hatte. Ein Ex-Kollege ist auch an der "Schwerfälligkeit" gescheitert bzw. wurde das dann nicht weiter verfolgt und auf Prio low eingestuft. Aber mit der Zeit wirds dringender... Alles in allem kann ich nicht viel zum SDK sagen, bis auf das in diversen Seiten eher die rohe Methode "entpacken,schreiben,packen" immer wieder genannt wird. Das Format läßt sich sicher auch recht gut ohne Doku verstehen, ist halt XML und kein Hexenwerk. Ansonsten einfach mal in der Doku von OOO für Developer nachgeschlagen. Würde wahrscheinlich nicht viel mehr Zeit kosten als die API zu erlernen.
 
Jap da hast du Recht. Ein Beispiel wo ich mich gegen das OpenOffice SDK entschieden habe war der folgende: Eine Word-Datei vorgegebener Struktur mit Platzhaltern. Die Platzhalter sollten dann eben durch einen Export mit den echten Daten gefüllt werden. Ging fast gar nicht mit dem Open Office SDK. Da haben wir uns dann doch dafür entschieden die Xml-Struktur roh einzulesen und dann einfach nach den Platzhaltern zu suchen und das ging alle male besser als mit der API. Man kann das Open Office SDK deshalb nur bis zu einem gewissen Komplexitätsgrad empfehlen.
 
Ja habe mich auch bisschen bei OO SDK eingelesen... sieht echt übel aus! beim Find habe aber immer noch nicht herausgefunden wie man auf Range zugreifen kann, wenn man was gefunden hat. Find liefert mir nur bool zurück, ob er gefunden hat oder nicht. Ich werde mal weiter mit Word machen. Habe mich schon eingearbeitet, da macht es kein Sinn bei anderen SDKs noch Zeit zu verschwenden. Bei Word ist alles auskommentiert und mir ist es lieber als mit eine COM Datei zu arbeiten wo es keine Kommentare vorhanden sind.
 
Hallo Roker,

angenommen du hast ein Range Objekt das den gesamten Text einschließt, dann wäre folgendes möglich:

Code:
Word.Range range = appWord.ActiveDocument.Content;
Word.Find find = range.Find;
find.ClearFormatting(); // Suche ohne Formate zu berücksichtigen
find.Text = "hello"; // Finde das Wort "hello" im Text
while(find.Execute()) // Suche solange wie du findest
    range.Text = "Hello World!"; // Ersetze alle Treffer durch "Hello World!"

Das Ganze würde in deinem Dokument jedesmal das Wörtchen "hello" durch "Hello World!" ersetzen, weil nach dem Aufrufen der range.Find.Execute() Methode das Range Objekt selbst dann auf den nächsten Treffer gesetzt wird. Es gibt keine Rückgabe eines neuen Range Objektes sondern man arbeitet immer mit dem was man gerade in der Bearbeitung hat.

Schau mal ob das deine Frage beantwortet, ansonsten habe ich deine Frage nicht so wirklich verstanden...

Also viel Erfolg!

Rossibaer
 
Ich habe ein kleines Problem... Wenn ich versuche eine Nested Table zu machen (Tabelle in der Tabelle), Ich erstelle eine Tabelle... 2x2 aber sobald ich versuche irgendwas in die Zellen 1,1 und 1,2 oder 2,1 und 2,2 einzufügen, gibt er mir immer wieder den Falschen Range Wert zurück. Sobald ich auf die Zelle 1,2 zugreife, bin ich im Range-bereich von 1,1. Das gleiche gilt für 2,1 und 2,2.
 
Poste mal den Code, bei der Beschreibung kann ich mir nicht viel darunter vorstellen woran es liegen könnte...
 
Naja so sieht der Teilcode aus.

Bei Initialisierung von c11 habe ich Range von x bis x+1
Bei Initialisierung von c12 habe ich Range von x + 2 bis x+3
Bei Initialisierung von c21 habe ich Range von x bis x+1

ich kann immer noch nicht vorstellen wieso!!

Code:
/// <summary>
/// Schreibt eine 2x2 Tabelle in der Zelle Adresse
/// </summary>
/// <param name="Adresse">Tabellenzelle, wo die innere Tabelle geschrieben werden soll.</param>
private void Kasseninfo(Cell Adresse)
{
    ///Erstelle die innere Tabelle in der Zelle 2:2
    Table innerTable = Adresse.Tables.Add(Adresse.Range, 2, 2, WdDefaultTableBehavior.wdWord9TableBehavior, missing);

    Cell c11 = innerTable.Cell(1, 1);
    Cell c12 = innerTable.Cell(1, 2);
    Cell c21 = innerTable.Cell(2, 1);
    //Cell c22 = innerTable.Cell(2, 2);

    ///Ändere die Schrift
    c11.Range.Font.Size = 8;
    c11.Range.Text = "Header Info Klein";

    ///Ändere Vertical Align auf Zentriert
    c11.VerticalAlignment = WdCellVerticalAlignment.wdCellAlignVerticalCenter;
    ///Ändere Tabellelänge auf 70%
    c11.PreferredWidthType = WdPreferredWidthType.wdPreferredWidthPercent;
    c11.PreferredWidth = 70;

    c12.Range.Text = "Linker Header Info"


    c21.Range.Font.Size = 12;
    c21.Range.Text = "Name Vorname\r\nStrasse und Nummer\r\nPLZ Stadt";


    //c22.Range.Text = string.Empty;

    ///Deaktiviere die Tabellenborders
    innerTable.Borders.Enable = 0;
}
 
ich schau mir das mal am WE genauer an, kann da momentan noch nichts Nennenswertes feststellen bzw. sehen wo genau die Ursache des Problems ist. Melde mich später wieder.
 
wie gesagt... ich greife auf die Zelle 1,1 bekomme den Range von 173-174.... dann Zelle 1,2 mit Range 175-176, dann Zelle 2,1 und bekomme Range von 173-174. Ich habe noch eine andere Nested Table, die aber 1x2 Ausrichtung hat. Damit habe ich kein Problem. Hmm ich habe jetzt ausprobiert... das Problem tauch immer wieder auf wenn man in der gleich spalte ist. Keine Ahnung wieso. Also für die 3x2 habe ich für Zelle 1,1 2,1, 3,1 die gleiche Range.


EDIT

Ich bin nochmal durchgegangen und habe einfach die Anzahl der Zeilen und Spalten aus der neue Tabelle ausgegeben. Komischerweise bekomme ich immer statt 2x2 Tabelle, eine 1x2 Tabelle.


EDIT 2

So ich habe da ein bisschen herumgetrickst.

Code:
Table innerTable = Adresse.Tables.Add(Adresse.Range, 1, 2, WdDefaultTableBehavior.wdWord9TableBehavior, missing);

[COLOR="Blue"]innerTable.Rows.Add(missing);[/COLOR]

Erstelle eine 1x2 Tabelle mit 2 Spalten und eine Zeile... dann füge eine Zeile hinzu... voilà, wir haben das gewünschten Ergebnis. Naja ein Workaround aber was solls... zumindest klappt es :D
 
Zuletzt bearbeitet:
Wie sagt mein Vater immer so schön: "Hält kein Dübel oder Leim, dann hau ich noch nen Nagel rein!" :D

Hey, Klasse! Wenn der Workaround funktioniert, ist's erstmal ok, optimieren kann man später immer noch... Was mich nur jedesmal etwas stutzig macht, ist dieses "missing", was du recht häufig beim Aufruf der Methoden verwendest. Was hat es damit auf sich? Würde da eher so vorgehen, dass ich die Parameter auch entsprechend angebe oder weg lasse.

Viele Grüße
Rossibaer
 
Zurück
Oben