エクセルでシートを分けて出力する処理を作成しています。
最初にSheet2を作成し、次にSheet1を作成することとし、
開発環境(Visual Studio .NET 2003)が入っているマシン上で
は正常に動作しますが、作成されたアプリケーションを同じ
ネットワーク内の別のマシン上で実行すると、下記部分でエラーとなります
Dim xlApp As Excel.Application
Dim xlWbs As Excel.Workbooks
Dim xlWb As Excel.Workbook
Dim xlWss As Excel.Sheets
Dim xlWs As Excel.Worksheet
xlApp = New Excel.Application
xlWbs = xlApp.Workbooks
xlWb = xlWbs.Add
xlWss = xlWb.Worksheets
xlWs = xlWss.Item("Sheet2") '←ここでエラー
'# DBアクセスとエクセルシート作成
MRComObject(xlWs) 'COMオブジェクトの解放処理
xlWs = Nothing
xlWs = xlWss.Item("Sheet1")
'# DBアクセスとエクセルシート作成
:
※エラー内容
try ~ catch を使用して下記のエラー内容を取得しています
インデックスが無効です
Interop.Excel
at Excel.Sheets.get_Item(Object Index)
at データ採取.frmNo1.Button1_Click(Object sender, EventArgs e)
System.RUntime.InteropServices.COMException (0x8002000B): インデックスが無効です。
at Excel.Sheets.get_Item(Object Index)
at データ採取.frmNo1.Button1_Click(Object sender, EventArgs e)
DB(MS-Access のMDBを使用)の格納場所、エクセル格納場所等のアクセス権は、
マシンの通常使用ユーザに対して全操作を許可しています(フルコントロール)。
また、エクセル操作時に「インデックス無効」のエラーが出る場合は、
たいてい、指定したシート名が存在していない時が多いのですが、
今回は、エクセルを新規に作成していることと、
開発マシン上では正常に動作していることから、原因が掴めていません。
何が原因となっているか分かりますでしょうか。
また、参考サイト等ありましたら教えてください。
新規のシート数はエクセルの設定で変えられるよ?
回答ありがとうございます。
>新規のシート数はエクセルの設定で変えられるよ
xlApp = New Excel.Application
・・の後に下記を追加しました。
xlApp.SheetsInNewWorkbook = 2 '新規作成のエクセルシート数
以上で、開発マシン以外でも作成できるようになりました。
『新規エクセル作成時は、"Sheet1"以外のシートへの書き込みを行う場合は、
予めシート数を指定しておく必要がある・・』ということですね。
これが、開発マシン上ではシート数の指定をしなくても作成できて、
開発マシン以外だと、シート数の指定が必要となるのは、
どうしてなのでしょうか。
一先ず、質問は解決としておきます。
ユーザーがエクセルのオプション設定画面で新規の
シート数を変更してるからでは?
…というかまず、
>たいてい、指定したシート名が存在していない時が多いのですが、
この時点で新規作成したシートのシート数及びシート名をテキストファイルに
ログ出力して確認するよね?確認したの?
新規作成時は、Sheet1, Sheet2, Sheet3が自動的に作成されていました。
>たいてい、指定したシート名が存在していない時が多いのですが、
と書いたのは、元々存在しているエクセルファイルに対して、
何か操作を行う場合には、「指定したシート名が存在していない」時に、
このエラーは出ていましたが、
今回は、新規作成時だったので、また挙動が違うのかと思いまして・・。
それとも・・、
xlApp = New Excel.Application
の時点では、シート数が1つしかないために、
まだSheet1しか作成出来ない・・ということなのでしょうか。
>ユーザーがエクセルのオプション設定画面で新規の
>シート数を変更してるからでは?
エクセルの設定はOfficeがインストールされた時と同じです。
一応確認して見ましたが、ツール⇒オプション⇒全般タブ の、
「新しいブックのシート数」は「3」になっていました。
どのタイミングでSheet1〜3のシート名を得ることが出来るようになるものなんでしょうか。
>それとも・・、
> xlApp = New Excel.Application
>の時点では、シート数が1つしかないために、
>まだSheet1しか作成出来ない・・ということなのでしょうか。
微妙に違うけど、正確に書くなら『新規ブックが作成されたとき』だから
>xlWb = xlWbs.Add
のタイミングだね。
まず、本来の姿を説明します。
VB からエクセルに命令を出す場合、実際の作業を行うのは Excel.exe です。
だからエクセルがインストールされていないと実行できません。
当然、実行時の設定はエクセルに設定されている情報がそのまま使われます。
つまり SheetsInNewWorkbook の値がツール⇒オプション⇒全般タブ の、
「新しいブックのシート数」そのものなんです。
そして xlWb = xlWbs.Add した時に、新規ブックを開いたのと同じく
SheetsInNewWorkbook の値が適用されなければなりません。
ところが、ツール⇒オプション⇒全般タブ の、「新しいブックのシート数」
が3にもかかわらず、デフォルト設定で"Sheet2"シートが無いらしい。
# ただし、実際のプログラム実行時のシート数とシート名はまだ調べてない
# ですよね?
それは本来の想定される結果ではありません。
挙動が違うということです。それは何かがおかしくなってるということでしょう。
例えば複数のバージョンのエクセルがインストールされてるとか、
過去のバージョンの情報が残ってるだとか、
そもそもエクセルが壊れてるだとか、
ユーザプロファイルが壊れてるだとか、
考えられる可能性を、色々テストして調査するしかありません。
>まだSheet1しか作成出来ない・・ということなのでしょうか。
知りません。自分で調べてください。Count プロパティの値を
出力して確認すればいいだけではないですか。それはボクの作業
ではありません。
>どのタイミングでSheet1〜3のシート名を得ることが出来るようになるものなんでしょうか。
それもステップ毎にプロパティから値を取得してみれば分かることでは?
おそらく正常に取得できる開発マシンでの動きが本来の姿なのでしょう。
で、実行環境で何が違うかは、地道にどこで処理が食い違うか調べてください。
なるほど、詳しく説明頂きありがとうございます。
>知りません。自分で調べてください。Count プロパティの値を
>出力して確認すればいいだけではないですか。
>それもステップ毎にプロパティから値を取得してみれば分かることでは?
こういう場合に何を調べればいいか分かっていなかったので、助かります。
どんな障害の時に何を調べればいいか?
というのは、やはり経験で覚えるものでしょうか。
参考書などを読んでいてもなかなか理解が深まらず、四苦八苦です。
また、今回は開発環境と違うマシンでエラーが出ましたが、
開発環境でない場合、debugモードで動かすことができません。
(それとも出来るもんなんでしょうか)
開発環境でない(Visual Studioがインストールされてない)場合、
どうやってデバッグをすればいいのでしょうか。
>どうやってデバッグをすればいいのでしょうか。
自己レスします。
xlWss = xlWb.Worksheets
xlWs = xlWss.Item("Sheet2")
の2行の間に下記を追加して、シート数とシート名を確認。
Dim strMsgBox As String = ""
For iii As Integer = 1 To xlWss.Count
xlWs = xlWss.Item(iii)
strMsgBox = strMsgBox & iii & " : " & xlWs.Name & vbCrLf
Next
MsgBox(strMsgBox)
としましたが、実行環境にて一度「xlApp.SheetsInNewWorkbook = 2」
を実行したためか、下記の結果が得られました。
1 : Sheet1
2 : Sheet2
その他の環境でも同様にして確認してみたいと思います。
色々ありがとうござました。
さらに追加で自己レスです。
1.元々の「新規作成時のシート数」を取得しておく
2.「新規作成時のシート数」を変更し、処理を実行
3.処理終了時に、元々の「新規作成時のシート数」に戻す
という風にすれば、処理終了後は元の設定に戻せる・・ですね。
プログラムの仕様で本来の環境を崩してしまっていた・・ということですね。
>どんな障害の時に何を調べればいいか?
>というのは、やはり経験で覚えるものでしょうか。
>参考書などを読んでいてもなかなか理解が深まらず、四苦八苦です。
50%くらいはエラーメッセージに書いてあります。
今回だって、"Sheet2"が無さそうって事でしょ?
参考書では『正解』が書いてあります。今回だって開発環境を
『正解』だと思って良い(思うしかない?)のですから、そこと
何が『違う』かを調べます。
経験で分かる過去の事例については、掲示板で情報が得られるのです
から経験不足が致命的な要因にはなりません。過去に起こったことの
無いエラーだったら?大事なのは『究極的にはエラー発生箇所の近辺で
使用している全てのオブジェクトの全てのプロパティについて、正常
環境と異常環境で比較する気構え』です。
ま、かといって先頭から全部調べるなんてしませんが。
(今回の場合、シートが取得できてないのだからその近辺を調べるのは
当然のこと)
>開発環境でない(Visual Studioがインストールされてない)場合、
>どうやってデバッグをすればいいのでしょうか。
既に回答済みです。回答者は1つの回答に先を見越したヒントを
たくさん盛り込みます。読み解けるかどうかは貴方の注意力次第です。
>>たいてい、指定したシート名が存在していない時が多いのですが、
>この時点で新規作成したシートのシート数及びシート名をテキストファイルに
>ログ出力して確認するよね?確認したの?
ログ出力処理を追加して確認します。このため、優れた開発者は簡単に
追加して利用し、必要無くなったら取り外せるログ出力モジュールを
用意しているものです。
>MsgBox
メッセージボックスを使うと確かに簡単にデータを確認できるのですが、
メッセージボックスにフォーカスが写り、処理がOKボタンを押すまで
止まってしまいます。
これによりプログラムの実行結果が変わる場合があります。特にイベント
関係では良くあることですので覚えておいてください。
>1.元々の「新規作成時のシート数」を取得しておく
>2.「新規作成時のシート数」を変更し、処理を実行
>3.処理終了時に、元々の「新規作成時のシート数」に戻す
1つの解決方法ではありますが、2.でエラーが起こって3.が実行されない
場合は考慮に入れてありますか?
一般には『ユーザ環境を一切変更しない』が鉄則です。
今回、SheetsInNewWorkbook はツール⇒オプション⇒全般タブ の、
「新しいブックのシート数」そのものであり、ユーザによる設定です。
テストプログラムで一時的に実行確認することはあっても、本番の
プログラムで変更することは避けます。
ではどうするか?
1.新規ブックを作成します。
2.シート数を確認します。
3.足りない場合はシートを追加。多い場合は削除します。
>という風にすれば、処理終了後は元の設定に戻せる・・ですね。
>プログラムの仕様で本来の環境を崩してしまっていた・・ということですね。
いやいや、よく考えてください。最初の質問の原因は分かっていません。
>xlApp.SheetsInNewWorkbook = 2
を追加したのはエラーを確認してここで質問した後でしょ?しかも
新規シート数が2に設定されてたなら最初の質問のエラーは起こらないはず。
しかも調査すると3で設定されていたと報告しましたよね?
…えーと、bhan さんが責任者なんですか?エラーの報告があると、その
内容をチェックする人がいると思いますが、これで原因調査・問題解決に
すると問題が起こる可能性大ですよ?
>2.でエラーが起こって3.が実行されない
>場合は考慮に入れてありますか?
・・考えてませんでした。
>1.新規ブックを作成します。
>2.シート数を確認します。
>3.足りない場合はシートを追加。多い場合は削除します。
このように作り直してみます。
>いやいや、よく考えてください。最初の質問の原因は分かっていません
確かに、原因を追究しないままでした。
元々は確かに「3」でしたが、今は「2」となっています。
このエクセルのあるマシン上では、
エクセルを使う業務は、今では私の作ったアプリでのみ使用するだけですので、
ひとまずこのまま使用することとしますが、原因追求は継続していきたいです。
#以下、余談です。
今の会社では、コボルを知ってる人はいるのですが、
すでに役員となってしまい直接業務に携わっていません。
私自身、去年からプログラム言語を使い始めたばかりで、
経験が少ないまま、社内のアプリを作成してます。
もっと多くのことを学びたいのですが、なかなか理解が進まず、
ネット上の情報と参考書を頼りに独学のみなので、
エラー処理等についてはネットや参考書でも分からないことが多いし、
いっそ、アプリ作成を主に仕事されてる方の元で勉強したいです・・。
ツイート | ![]() |