Entwickler-Ecke

IO, XML und Registry - PDF-Konvertierung von Office-Dokumenten


Schlüsselbein - Fr 31.01.14 11:24
Titel: PDF-Konvertierung von Office-Dokumenten
Hallo,

bin mir leider nicht sicher, ob ich im richtigen Forum bin, entschuldigt, falls nicht.

Ich habe ein COM-Add-In für alle Office-Programme geschrieben, welches diese mit einem zusätzlichen Button ausrüstet. Dafür habe ich using Microsoft.Office.Core; benutzt.

Beim Klicken wird das Event

C#-Quelltext
1:
2:
3:
4:
private void MyButton_Click(CommandBarButton cmdBarbutton, ref bool cancel)
{
            
}

ausgelöst. Und hier würde ich gerne ein PDF-Konverter reinschreiben. D.h., das offene Office-Dokument soll als PDF gespeichert werden auf D:\.
Habe schon gesucht und gesucht, allerdings nicht so ganz das richtige gefunden.

Wenn jemand einen guten Link oder mir sonstige Hinweise geben kann, wäre ich dankbar.

Grüße

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


Ralf Jansen - Fr 31.01.14 11:47

Howtos

Excel - http://msdn.microsoft.com/en-us/library/office/bb407651.aspx
Word - http://msdn.microsoft.com/en-us/library/office/bb412305.aspx

für Powerpoint gibts scheinbar kein Tutorial aber zumindest die gleiche Funktionalität

Powerpoint - http://msdn.microsoft.com/en-us/library/office/ff746080.aspx

und in Outlook müßte man wenn man eine Mail drucken will die erst in Word öffnen udn dann von da das PDF erzeugen

Outlook - http://www.slipstick.com/developer/code-samples/save-outlook-email-pdf/


Schlüsselbein - Fr 31.01.14 11:56

Danke für deine schnelle Antwort. Werde ich mir mal anschauen.
Gildet das auch für Office 2010?


Ralf Jansen - Fr 31.01.14 12:46

Sehr wahrscheinlich. Die API ist da eigentlich gleich.


Schlüsselbein - Fr 31.01.14 12:55

In dem Excel Link unter dem Punkt 3 werden mir bei

C#-Quelltext
1:
2:
ApplicationClass excelApplication = new ApplicationClass();
Workbook excelWorkBook = null;

diese Fehlermeldung angezeigt:
Der Interoptyp "Microsoft.Office.Interop.Excel.ApplicationClass" kann nicht eingebettet werden. Verwenden Sie stattdessen die entsprechende Schnittstelle.

Markiert wird "ApplicationClass"

Was stimmt nicht ?

Moderiert von user profile iconTh69: C#-Tags hinzugefügt


Tranx - Fr 31.01.14 13:00

Eine Möglichkeit Office-Komponenten zu pdf zu konvertieren ist die Installation eines PDF-Druckers (Foxit-Reader, Free-PDF). Dann brauchst Du die Dokumente - egal von welchem Programm aus - nur noch zu drucken (Meistens wird der Dokumentenname mit .pdf als Vorgabename für die zu speichernde Datei benutzt).


Schlüsselbein - Fr 31.01.14 13:02

Die Dokumente sollen allerdings nicht gedruckt werden, sondern erstmal nur gespeichert werden.


Tranx - Fr 31.01.14 13:50

Der "Drucker" speichert die Dokumente, wenn Du das wünschst. Beim Free-PDF erledigst Du das z.B. über "Datei ablegen". Dann wählst Du das Verzeichnis aus nur änderst ggfs. den Dateinamen.

Vorteil: Du kannst dies für JEDES Programm mit Druckerausgabe nutzen udn sogar diesen "Drucker" als Standarddrucker definieren.


Schlüsselbein - Fr 31.01.14 13:55

Achso, dann wäre das natürlich praktisch. Bleibt nur noch die Frage, wie man das in den C#-Code einbringt. :(


Ralf Jansen - Fr 31.01.14 14:11

Zitat:
Der Interoptyp "Microsoft.Office.Interop.Excel.ApplicationClass" kann nicht eingebettet werden. Verwenden Sie stattdessen die entsprechende Schnittstelle.


Dann solltest du das embedden für diese Referenz ausschalten.
Im Solution Explorer bei den Referenzen die Interop Assembly raussuchen und in den Properties "Embedd Interop Types" auf false setzen.


Schlüsselbein - Fr 31.01.14 17:40

Den Solution Explorer kann ich einfach nicht finden. :(
Wo ist der?


Ralf Jansen - Fr 31.01.14 17:43

Das ist das zentrale Ding wo alle Projekte Dateien und so weiter aufgezählt sind. Das kannst du eigentlich nicht übersehen ;) Ich weiß leider nur nicht wie das in einem deutschen VS heißt :(


Th69 - Fr 31.01.14 21:13

Projektmappen-Explorer [http://msdn.microsoft.com/de-de/library/bbck0dh6%28v=vs.100%29.aspx] ;-)


Schlüsselbein - Mo 03.02.14 12:35

Achso! Ja ok habe es dann schnell gefunden :)

Zitat:
Im Solution Explorer bei den Referenzen die Interop Assembly raussuchen und in den Properties "Embedd Interop Types" auf false setzen.


Hat geklappt. Danke für den Hinweis.

Also mit meinem Add-In bin ich jetzt soweit:
In dem Click-Event wird eine feste Datei + Pfad genommen und an einem festen Pfad gespeichert.


C#-Quelltext
1:
2:
string Quellpfad = @"D:\Test.xlsx";
string Zielpfad = @"D:\Test.pdf";


Allerdings möchte ich erreichen, dass in der Variable Quellpfad der Name (+ Pfad) des aktuell offenenen Office-Dokuments steht und diese folgendermaßen gespeichert wird:

D:\(UrsprünglicherNameDerDatei).pdf

Es soll also der Name beibehalten werden, nur die Extension soll pdf sein.
Ich brauche somit also eine Möglichkeit, mit C# den Namen des aktuell offenen Office-Dokuments herauszubekommen. Nach langem Suchen habe ich lediglich Beispiele für einzelne Office-Programme bekommen, meist Word und Excel.
Dies soll aber in allen Office-Programmen gelten. (Erstmal Word,Excel,PowerPoint und Outlook)

Hat jemand eine Idee, wie ich das mache?

In VB wäre das leicht, aber ich möchte das in C# schreiben.

Quelltext
1:
Zielpfad = Left(ActiveDocument.Name, InStr(1, ActiveDocument.Name, ".") - 1) & ".pdf"                    


Für jeden Hinweis wäre ich sehr dankbar.

Grüße


Ralf Jansen - Mo 03.02.14 12:55

Unter der Annahme das in ActiveDocument.Name der Name mit Extension aber ohne Path steht dann z.B. so.


C#-Quelltext
1:
string destination = Path.Combine(@"D:\", Path.ChangeExtension(ActiveDocument.Name, "pdf"));                    


Schlüsselbein - Mo 03.02.14 13:14

Danke für die schnelle Antwort! Aber:


C#-Quelltext
1:
string sourcePath = Path.Combine(@"D:\", Path.ChangeExtension(ActiveDocument.Name, "pdf"));                    

Bei "ActiveDocument": Der Name "ActiveDocument" ist im aktuellen Kontext nicht vorhanden.

Was muss ich tun?


Ralf Jansen - Mo 03.02.14 13:17

Du hast in deinem Beispiel ActiveDocument.Name benutzt darum bin ich davon ausgegangen das es das gibt bzw. du schon hast. Wenn du das so in einem VB Script hinbekommen hast solltest du in C# genauso an das aktive Dokument kommen (und dessen Namen) kommen. Die API ist ja die gleiche. Den Namen des pdf Files bekommst du dann wie gezeigt erzeugt.


Schlüsselbein - Mo 03.02.14 13:27

Ich habe gerade das Gefühl, ich seh den Wald vor lauter Bäumen nicht mehr.

In dem Beispielcode gibt es vorher doch auch kein ActiveDocuement.Name. Ich poste ihn mal hier ganz.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
''Excel-Datei exportieren 
Sub pdfexport()
Dim strFilePath  As String
Dim strFileName  As String

strFilePath = "D:\"
strFileName = Left(ActiveWorkbook.Name, InStr(1, ActiveWorkbook.Name, ".") - 1) & ".pdf"

ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=strFilePath & strFileName, Quality:=xlQualityStandard, _
                                    IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False

End Sub


Aber meine Frage, was ich tun muss, damit ActiveDocument erkennt, besteht immernoch.
Entschuldige, wenn ich hier sehr unwissend rüberkomme, bin grad sehr verwirrt. :(


Ralf Jansen - Mo 03.02.14 14:13

Zitat:
Entschuldige, wenn ich hier sehr unwissend rüberkomme, bin grad sehr verwirrt. :(


Vorsicht. Das ist ansteckend.

Ich rate mal vor mich hin und vermute mal das ActiveDokument oder in deinem jetzt gezeigten Code ActiveWorkbook einfach Properties der Application Klasse sind. Schau doch einfach mal nach was die so bietet.


Schlüsselbein - Mo 03.02.14 15:55


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
Microsoft.Office.Interop.Excel.ApplicationClass excelApplication = new ApplicationClass();
Workbook excelWorkBook = null;

try
{
     string test2 = excelApplication.ThisWorkbook.FullName;  // Pfad einschließlich Dateiname ?
     string test3 = excelApplication.ThisWorkbook.Path;      // nur der Name ?
     string test4 = excelApplication.Name;                   // nur der Pfad ?

     File.AppendAllText(@"D:\test2.log", test2);
     File.AppendAllText(@"D:\test3.log", test3);
     File.AppendAllText(@"D:\test4.log", test4);
 }
catch (Exception ex)
{
     MessageBox.Show("Fehler:" + ex.Message + "\n" + ex.StackTrace, "Fehler");
}


ergibt die Fehlermeldung:
Fehler: 0x800A03EC
bei Microsoft.Office.Interop.Excel.ApplicationClass.get_ThisWorkbook() bei Test.Connect.MyButton_Click(CommandBarButton cmdBarButton, Boolean& cancel) in B:\-Pfad zum Projekt-\Connect.cs:Zeile 135. (in dem Zitat oben ist das Zeile 6)

Fällt jemandem auf, was ich falsch mache?


Ralf Jansen - Mo 03.02.14 16:13

Du liest die Doku nicht vollständig ;)

Zitat aus der Hilfe zu ThisWorkBook [http://msdn.microsoft.com/en-us/library/office/ff193227%28v=office.14%29.aspx]
Zitat:
This property can be used only from inside Microsoft Excel. You cannot use it to access a workbook from any other application.


Schlüsselbein - Mo 03.02.14 16:38

Hm :(

Gibt es also generell keine Lösung für mein Problem?


Ralf Jansen - Mo 03.02.14 16:55

Bestimmt gibt es eine Lösung. Aber warum bist du von ActiveDocument zu ActiveWorkBook zu ThisWorkBook gesprungen? Das sieht schwer nach blindem Try&Error aus. Vielleicht erstmal die Doku lesen, die funktionweise der API zumindest ansatzweise verstehen und dann rumprobieren?


Schlüsselbein - Mo 03.02.14 17:05

Ich war die ganze Zeit bei ThisWorkbook. ActiveDocument und ActiveWorkbook waren nur Beispiele aus VB.