C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: Officeの印刷


(過去ログ 77 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■45278 / inTopicNo.1)  Officeの印刷
  
□投稿者/ 初心者です (2回)-(2010/01/08(Fri) 00:33:08)

分類:[C#] 

VS2008 C# を使用しています。

Office(Word,Excel)の印刷を行いたいのですが、
どのOfficeのバージョン(2000,2003,2007)かが不明なので
「Microsoft Excel xx.x Object Library」を使用した開発ができません。

リフレクションを利用したレイトバインディングで行っていて、
開くことはできるようになりました。
印刷のほうはどのように行えばよいのでしょうか。

かなり困っていまして、よろしくお願いいたします。
引用返信 編集キー/
■45284 / inTopicNo.2)  Re[1]: Officeの印刷
□投稿者/ 魔界の仮面弁士 (1439回)-(2010/01/08(Fri) 15:33:11)
No45278 (初心者です さん) に返信
> 印刷のほうはどのように行えばよいのでしょうか。
単純印刷なら、既定のプリンタへ出力のために
  ProcessStartInfo psi = new ProcessStartInfo(@"C:\sample.docx");
  psi.Verb = "PRINT";
  Process.Start(psi);
という方法が使えます。


> 印刷のほうはどのように行えばよいのでしょうか。
Workbook や Document に PrintOut メソッドがあります。

ただし、Office のバージョンによって引数の数が異なります。
通常は気にする必要は無いかも知れませんが、処理内容によっては、
その呼びわけのために、実行時判定が必要となるケースがあるかも知れません。

引用返信 編集キー/
■45285 / inTopicNo.3)  Re[2]: Officeの印刷
□投稿者/ 魔界の仮面弁士 (1440回)-(2010/01/08(Fri) 15:49:10)
No45284 (魔界の仮面弁士) に追記
>>印刷のほうはどのように行えばよいのでしょうか。
> Workbook や Document に PrintOut メソッドがあります。
> ただし、Office のバージョンによって引数の数が異なります。

たとえば Excel の場合、このメソッドには
 引数 7 個版 : DispId(0x389)
 引数 8 個版 : DispId(0x6ec)
 引数 9 個版 : DispId(0x939)
の 3 種類があり、それぞれ、下記の名前で実装されています。

<Excel 2007>
 PrintOut  メソッド … 引数 9 個版(0x939)
 _PrintOut メソッド … 引数 8 個版(0x6ec)
 __PrintOutメソッド … 引数 7 個版(0x389)

<Excel 2000, 2002, 2003>
 PrintOut  メソッド … 引数 8 個版(0x6ec)
 _PrintOut メソッド … 引数 7 個版(0x389)

<Excel 5.0, 95, 97>
 PrintOut  メソッド … 引数 7 個版(0x389)


Word の場合は、名前付けのルールが異なります。

<Word 2007, 2002>
 PrintOut    メソッド … 引数 18 個版(0x1be)
 PrintOut2000メソッド … 引数 18 個版(0x1bc)
 PrintOutOld メソッド … 引数 14 個版(0x6d)

<Word 98>
 PrintOut    メソッド … 引数 14 個版(0x6d)

# Word 2003, 2000, 97, そして95以下については未調査。m(_ _)m

引用返信 編集キー/
■45290 / inTopicNo.4)  Re[3]: Officeの印刷
□投稿者/ 初心者です (3回)-(2010/01/08(Fri) 18:06:46)
2010/01/08(Fri) 20:41:21 編集(投稿者)
2010/01/08(Fri) 19:25:12 編集(投稿者)

No45285 (魔界の仮面弁士 さん) に返信

魔界の仮面弁士 さん
ありがとうございます。

Workbook や Document に PrintOut を使用したいので、
バージョンによって、替えるようにします。


oWord = docApp.GetType().InvokeMember("Documents", BindingFlags.GetProperty, null, docApp, null);

oDoc = oWord.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, oWord,
new object[]{oFilePath,
oMissing, oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing});

oDocPrint = oWord.GetType().InvokeMember("PrintOut", BindingFlags.GetProperty, null, oWord,
new object[] {
oTrue, oFalse, range, oMissing, oMissing, oMissing,
items, copies, pages, pageType, oFalse, oTrue,
oMissing, oFalse, oMissing, oMissing, oMissing, oMissing
});

のような感じ行いたいのですが印刷ができません。
どのようにすればよいのでしょうか

引用返信 編集キー/
■45297 / inTopicNo.5)  Re[4]: Officeの印刷
□投稿者/ Atata!! (7回)-(2010/01/09(Sat) 01:10:07)
Atata!!です。

Office PIAを使用せずにExcelとWordを印刷するのであればIPrintインターフェース経由で印刷できます。
↓私のサイトにサンプルがあります。
www5.plala.or.jp/atata/net/chap24.html

なお、Excelは先頭1シートのみが印刷されるため(多分)、
これが問題になるのであれば適用することは出来ないと思います。
また、基本的にリフレクションを利用したレイトバインディングと組み合わせて使用することになると思います。

引用返信 編集キー/
■45301 / inTopicNo.6)  Re[4]: Officeの印刷
□投稿者/ 魔界の仮面弁士 (1442回)-(2010/01/09(Sat) 10:07:42)
No45290 (初心者です さん) に返信
> new object[]{oFilePath,
> oMissing,  oMissing,  oMissing,  oMissing,  oMissing,
> oMissing,  oMissing,  oMissing,  oMissing,  oMissing,
> oMissing,  oMissing,  oMissing,  oMissing,  oMissing});

oMissing とは、System.Type.Missing の事でしょうか?

だとすれば、optional パラメータは省略可能ですので、
上記は new object[]{oFilePath} でも動作します。


それと、VB のアセンブリを使う事に抵抗が無ければ、
> oWord = docApp.GetType().InvokeMember("Documents", BindingFlags.GetProperty, null, docApp, null);
> oDoc = oWord.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, oWord, new object[]{oFilePath, …});
というコードは、Microsoft.VisualBasic.DLL を参照設定すると、
  using Microsoft.VisualBasic;
  using VB = Microsoft.VisualBasic.Interaction;
としておいた上で、
  oWord = VB.CallByName(docApp, "Documents", CallType.Get);
  oDoc = VB.CallByName(oWord, "Open", CallType.Method, oFilePath);
のように、比較的短く記述することができますよ。


> のような感じ行いたいのですが印刷ができません。
それはエラーになるという事ですか?
だとしたら、その例外(あるいは例外の InnerException)は何になっていますか?


> oDocPrint = oWord.GetType().InvokeMember("PrintOut", BindingFlags.GetProperty, null, oWord,
> new object[] {
> oTrue,  oFalse,  range,  oMissing,  oMissing,  oMissing,
> items,  copies,  pages,  pageType,  oFalse,  oTrue,
> oMissing,  oFalse,  oMissing,  oMissing,  oMissing,  oMissing
> });
やりたい事は、「oDoc」に読み込まれた文書を印刷することですよね?

しかし、oWord は Documents オブジェクトです。上記の構文で呼び出されるのは、
『Documents オブジェクトの PrintOut プロパティ』となる事に注意してください。

Documents には、PrintOut というプロパティもメソッドもありませんので、
当然、呼び出すことはできません。

ここで呼び出すべきは、『Document オブジェクトの PrintOut メソッド』です。
# あるいは、Document.PrintOut の代わりに、Application.PrintOut でも役目は果たせますが、
# oDoc を印刷するという視点から見ると、Document.PrintOut の方が自然でしょうね。


なお、Word 2007 の場合、
 Application.PrintOut メソッド…引数 19個
 Document.PrintOut    メソッド…引数 18個
という定義になっています。引数の数が違いますのでご注意あれ。
(もっとも optional 引数なので、引数指定は省略することもできますが)

引用返信 編集キー/
■45303 / inTopicNo.7)  Re[5]: Officeの印刷
□投稿者/ 魔界の仮面弁士 (1444回)-(2010/01/09(Sat) 12:03:31)
No45285 (魔界の仮面弁士) に追記
> <Excel 2000, 2002, 2003>
>  PrintOut  メソッド … 引数 8 個版(0x6ec)
>  _PrintOut メソッド … 引数 7 個版(0x389)

PrintOut や Workbooks.Open などでは、下位互換メソッドが用意されていますが、
すべてのメンバーがそうというわけではありません。

たとえば Excel の Range.Insert メソッドを見てみると、
Excel 2000 以下では引数 1個、Excel 2002 以降では引数 2 個です。

しかし、Insert の下位互換メソッドは用意されませんでした。
Excel 2002/2003/2007 には引数 1 個版の Insert メソッドは実装されておらず、
また、引数定義が変化したメソッドに、新たな DispId が振られる事もありませんでした。
(Range.Insert の DispId は 0xfc です)


このように、Office のオートメーション ライブラリでは、必ずしもバイナリ互換性が
保証されているわけではため、複数バージョンに対応させようとするのであれば、
各バージョンの違いを充分に調査しておく事をお奨めします。

とりあえず作ってみて、後で動かしてみて動作確認という流れだと、
問題点の切り出しが難しくなりがちですし。

# 旧バージョンでは戻り値無し(void定義)だったメソッドが、バージョンが上がると
# Variantを返す(戻り値object)ようになったメソッドさえあったような…うろ覚え。


■No45301 (魔界の仮面弁士) に追記
> なお、Word 2007 の場合、
>  Application.PrintOut メソッド…引数 19個
>  Document.PrintOut    メソッド…引数 18個
> という定義になっています。引数の数が違いますのでご注意あれ。
> (もっとも optional 引数なので、引数指定は省略することもできますが)

.NET でも非.NET 環境でもそうですが、Office の複数バージョンに対応させる場合には、
 (案1) 各バージョンごとの環境で参照設定をやりなおし、別 EXE として提供する。
 (案2) Office バージョンにあわせて、呼び出すメソッドを変更する。
 (案3) 常に下位バージョンのメソッドを使う。上位バージョンのメソッドは使わない。
 (案4) 常に現行バージョンのメソッドを使う。ただし、追加された optional 引数は指定しない。
のいずれかが利用されます(これらを併用する事もあるでしょう)。

個人的には、主に 案3/案4 をよく利用しています。


案1 は確実ですが、開発環境を用意するのが一苦労ですし、配布の手間もかかります。


案2 は「利用できる場合には、上位バージョンの機能を利用したい」といった場合や、
動作の変化した機能を吸収するために用いられます。
案3/案4と併用して使われることも多いですね。

ただし、その判定方法に注意してください。大抵、Office のバージョンは、
Application オブジェクトの Version プロパティから得る事になりますが、
この値は数値ではなく文字列ですので、比較の際には注意が必要です。
http://support.microsoft.com/kb/282034/ja
また、この値には "8.0a" のように、アルファベットが混じる事もあります。
http://support.microsoft.com/kb/232652/en-us


そして 案3ですが、これは下位互換メソッドがある場合にのみ利用できます。

レイトバインドで呼ぶ場合には、たとえばこのようにします。( No45301 も参照 )
変数 oDoc は、Word の Document オブジェクトです。
  // using Microsoft.VisualBasic;
  // using VB = Microsoft.VisualBasic.Interaction;

  const string Document_PrintOut = "[DispID=109]";
  object[] args = { Type.Missing, Type.Missing, … };  // 引数14個
  VB.CallByName(oDoc, Document_PrintOut, CallType.Method, args);

これは、Document の「DispId が 109(=0x6d) なメンバー」すなわち、
『引数 14 個版の PrintOut メソッド』を指定しているところです。( No45285 を参照 )

この場合、Word 97/98 などでは、
 oDoc.PrintOut(Type.Missing, …);     // 引数14個
に相当するコードが呼び出され、Word 2000 以降では
 oDoc.PrintOutOld(Type.Missing, …);  // 引数14個
に相当するコードが呼び出されます。

引数をすべてする場合には、
  VB.CallByName(oDoc, Document_PrintOut, CallType.Method);
のように記述する事もできます。


そして 案4 については、
  VB.CallByName(oDoc, "PrintOut", CallType.Method, oTrue, oFalse, range);
のような呼び出しを意味します。
もちろん、Microsoft.VisualBasic.DLL に頼らず、
  docApp.GetType().InvokeMember("PrintOut", BindingFlags.InvokeMethod, null,
      docApp, new oject[] {oTrue, oFalse, range});  // 最大14個まで指定可能
と記述しても OK です。

この場合、Word 97/98 などでは、
 oDoc.PrintOut(oTrue, oFalse, range, Type.Missing, …);     // 引数14個
Word 2007 なら、
 oDoc.PrintOut(oTrue, oFalse, range, Type.Missing, …);     // 引数18個
に相当するコードが実行されます。上位バージョンの環境で実行した場合には、
15 個目以降は Type.Missing で埋められる事になります。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -