DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ファイルの保存について

環境/言語:[VB.NET]
分類:[.NET]

SaveFileDialogを使い、Excelのファイルを保存したいのですが、

(前略)

Dim rlt As DialogResult
rlt=SaveFileDialog1.ShowDialog

SaveFileDialog1.InitialDirectory="C:\"

SaveFileDialog1.Filter="エクセル形式(*.xls)|*.xls"

If rlt=DialogResult.OK Then
xlBook.SaveAs(SaveFileDialog1.FileName)
ElseIf rlt=DialogResult.Cancel Then
Close()
End If


と組んでみましたが、どうもうまくいきません。
VB.NETでデータを書き込んだExcelファイルを、保存先指定して保存といったプロセスを踏みたいのですが・・・ 

xlBook.SaveAs(SaveFileDialog1.FileName)というところが原因なのではないかということは分かるのですが、そこをどのように変えるべきなのかが分かりません。

ここを調べてみろといったリンクでも結構なので、教えていただけませんでしょうか。
お手数ではございますが、よろしくお願いいたします。
こんにちは、じゃんぬねっと です。

■No9516に返信(なべさんの記事)
> rlt=SaveFileDialog1.ShowDialog
> SaveFileDialog1.InitialDirectory="C:\"
> SaveFileDialog1.Filter="エクセル形式(*.xls)|*.xls"

ここ、順番おかしくないですか?
ShowDialog() する前にフィルタ等は設定するのではないのでしょうか?

> xlBook.SaveAs(SaveFileDialog1.FileName)というところが原因なのではないかということは分かるのですが、
> そこをどのように変えるべきなのかが分かりません。
> ここを調べてみろといったリンクでも結構なので、教えていただけませんでしょうか。

まず、そこにブレイク ポイントを仕掛けて、
SaveFileDialog1.FileName に何が格納されているか教えてください。
じゃんぬねっと様、ご返答ありがとうございます。


> ここ、順番おかしくないですか?
> ShowDialog() する前にフィルタ等は設定するのではないのでしょうか?

失礼いたしました。こちらの方は手直しいたしました。


> まず、そこにブレイク ポイントを仕掛けて、
> SaveFileDialog1.FileName に何が格納されているか教えてください。

基礎的な質問をして申し訳ございませんが、何が格納されているかを見るためには、ブレークポイントを仕掛けた跡にどのような操作をすればよろしいのでしょうか。

基本から理解しておらず、大変申し訳ございませんが、ご回答いただければ幸いです。
こんなのどうでしょう。

http://www.amazon.co.jp/exec/obidos/ASIN/4891003529/250-2654267-3429800

ここからたどりました。

http://www.google.co.jp/search?num=100&hl=ja&c2coff=1&rls=GGLD%2CGGLD%3A2005-07%2CGGLD%3Aen&q=VisualStudio+%E3%83%87%E3%83%90%E3%83%83%E3%82%B0+%E5%85%A5%E9%96%80+%E6%9B%B8%E7%B1%8D&lr=lang_ja
こんにちは、じゃんぬねっと です。

■No9519に返信(なべさんの記事)
> 失礼いたしました。こちらの方は手直しいたしました。

ははは、要らぬ心配だったようですね。(^-^*)

> 基礎的な質問をして申し訳ございませんが、何が格納されているかを見るためには、
> ブレークポイントを仕掛けた跡にどのような操作をすればよろしいのでしょうか。
> 基本から理解しておらず、大変申し訳ございませんが、ご回答いただければ幸いです。

Visual Studio .NET を使用している前提で宜しいですか?
次の手順を踏んでください。

 ・デバッグ ビルドで実行すると、そのラインでブレイクします。
 ・「OpenFileDialog1.FileName」の部分を選択状態 (反転) にします。
 ・右クリック メニューから、[ウォッチ式に追加 (W)] を選択します。
 ・ウォッチのダイアログを見ると、値の確認ができます。

なお、単純な変数またはプロパティは、マウス カーソルをポイントするだけで、
ツールチップに内容が表示されます。

VS は大変良く出来た IDE です。
なるべく、細部まで弄り倒してみてください。
GUI の操作は、頭ではなく体で覚えた方が、他所の開発環境でも役に立ちますよ。

# 中センセの薦める通り、書籍に頼るのもひとつの手ですが。
■No9521に返信(中博俊さんの記事)
> こんなのどうでしょう。
>
> http://www.amazon.co.jp/exec/obidos/ASIN/4891003529/250-2654267-3429800
>
> ここからたどりました。
>
> http://www.google.co.jp/search?num=100&hl=ja&c2coff=1&rls=GGLD%2CGGLD%3A2005-07%2CGGLD%3Aen&q=VisualStudio+%E3%83%87%E3%83%90%E3%83%83%E3%82%B0+%E5%85%A5%E9%96%80+%E6%9B%B8%E7%B1%8D&lr=lang_ja

ありがとうございます。参考にして見ます。
格納されている値ですが、ファイル保存ダイアログで指定した、"C:\test.xls"というものが格納されていました。しかし、保存はできていない状態になります。
こんにちは、じゃんぬねっと です。

■No9526に返信(なべさんの記事)
> 格納されている値ですが、ファイル保存ダイアログで指定した、
> "C:\test.xls"というものが格納されていました。
> しかし、保存はできていない状態になります。

では、もっと前の段階に問題があるのでしょう。
こちらを参考にしてください。非常に詳しいです。
http://www.bcap.co.jp/hanafusa/dotnet/Excel01.htm
■No9536に返信(じゃんぬねっとさんの記事)
>
> では、もっと前の段階に問題があるのでしょう。
> こちらを参考にしてください。非常に詳しいです。
> http://www.bcap.co.jp/hanafusa/dotnet/Excel01.htm

ありがとうございます。こちらの方を確認させていただきました。
それを参考にもいたしまして、自分で組んでみたものを載せますので、原因と思われる箇所をご指摘いただければと思います。

お手数ですが、よろしくお願いいたします。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet

xlApp = CreateObject("Excel.Application")
xlBook = CType(xlApp.Workbooks.Add, Excel.Workbook)
xlSheet = CType(xlBook.Worksheets(1), Excel.Worksheet)

xlApp.Visible = True

xlBook = xlApp.Workbooks.Open(ファイルの保存先)

CType(xlBook.Sheets.Item("Sheet1"), Excel.Worksheet).Range("A1").Value = Textbox1.Text

xlApp.DisplayAlerts = False
xlApp.Quit()
xlApp.DisplayAlerts = True

Dim rlt As DialogResult
SaveFileDialog1.InitialDirectory = "C:\"
SaveFileDialog1.Filter = "エクセル形式(*.xls)|*.xls"
rlt = SaveFileDialog1.ShowDialog

If rlt = DialogResult.OK Then
xlBook.SaveAs(SaveFileDialog1.FileName)
ElseIf rlt = DialogResult.Cancel Then
Close()
End If

End Sub
> xlSheet = CType(xlBook.Worksheets(1), Excel.Worksheet)
これだと、Worksheetsコレクションを解放できなくなってしまいます。
本来であれば、
Dim xlSheets As Excel.Sheets = CType(xlBook.Worksheets, Excel.Sheets)
Dim xlSheet As Excel.Worksheet = CType(xlSheets.Item(1), Excel.Worksheet)
のようにして、かつ、使用後には、
System.Runtime.InteropServices.Marshal.ReleaseComObject()
による解放が必要でしょう。


> xlApp.DisplayAlerts = False
> xlApp.Quit()
> xlApp.DisplayAlerts = True

ここで、Excel本体を終了させていますよね。その後で、

> xlBook.SaveAs(SaveFileDialog1.FileName)

のようにファイル保存を行うというのは、順番がおかしくないですか?
ファイルを保存してから終了させないと。
魔界の仮面弁士様、ご指摘ありがとうございました。

ご指摘いただいた箇所を修正しましたところ、保存はできるようになりました。

しかし、SaveFileDialogの保存をクリックするのですが、1回目では何も反応がなく、2回目にクリックすると処理が行われるという状態になっております。

プログラムの組み方が原因なのでしょうか。
> ご指摘いただいた箇所を修正しましたところ、保存はできるようになりました。
『ReleaseComObject()』の部分も修正されましたか?
Worksheetsコレクションだけでなく、Workbooksコレクションや
Rangeコレクションにおいても、同様の問題がありますよ。


> プログラムの組み方が原因なのでしょうか。
おそらくそうだとは思いますが、「修正後のコード」が提示されていないので、
問題のある箇所を具体的に指摘する事はできません。(^^;
■No9571に返信(魔界の仮面弁士さんの記事)
>>ご指摘いただいた箇所を修正しましたところ、保存はできるようになりました。
> 『ReleaseComObject()』の部分も修正されましたか?
> Worksheetsコレクションだけでなく、Workbooksコレクションや
> Rangeコレクションにおいても、同様の問題がありますよ。
>
>
>>プログラムの組み方が原因なのでしょうか。
> おそらくそうだとは思いますが、「修正後のコード」が提示されていないので、
> 問題のある箇所を具体的に指摘する事はできません。(^^;

大変失礼いたしました。
変更後のコードを提示いたします。
お手数ですが、よろしくお願いいたします。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim xlApp As Excel.Application = CreateObject("Excel.Application")
Dim xlBook As Excel.Workbook = CType(xlApp.Workbooks.Ad, Excel.Workbook)
Dim xlSheets As Excel.Sheets = CType(xlBook.Worksheets, Excel.Sheets)
Dim xlSheet As Excel.Worksheet = CType(xlSheets.Item(1), Excel.Worksheet)


xlBook = xlApp.Workbooks.Open(ファイルの保存先)

CType(xlBook.Sheets.Item("Sheet1"), Excel.WorkSheet).Range("A1").Value = TextBox1.Text


xlApp.DisplayAlerts = False

Dim rlt As DialogResult
SaveFileDialog1.InitialDirectory = "C:|"
SaveFileDialog1.Filter = "エクセル形式(*.xls)|*.xls"
rlt = SaveFileDialog1.ShowDialog

If rlt=DialogResult.OK Then
xlBook.SaveAs(SaveFileDialog1.FileName)

ElseIf rlt = DialogResult.Cancel Then
Close()

End If

xlApp.Quit()
xlApp.DisplayAlerts = True


MRComObject(xlSheet)
MRComObject(xlSheets)
MRComObject(xlBook)
MRComOnject(xlApp)

End Sub


Private Sub MRComObject(ByVal objxl As Object)

Try

System.Runtime.InteropServices.Marshal.ReleaseComObject(objxl)

Catch

Finally
objxl = Nothing

End Try

End Sub

> Dim xlApp As Excel.Application = CreateObject("Excel.Application")
> Dim xlBook As Excel.Workbook = CType(xlApp.Workbooks.Ad, Excel.Workbook)
> Dim xlSheets As Excel.Sheets = CType(xlBook.Worksheets, Excel.Sheets)
> Dim xlSheet As Excel.Worksheet = CType(xlSheets.Item(1), Excel.Worksheet)
> xlBook = xlApp.Workbooks.Open(ファイルの保存先)
> CType(xlBook.Sheets.Item("Sheet1"), Excel.WorkSheet).Range("A1").Value = TextBox1.Text

弁さんが言うことを理解できていないのであればExcel操作はしてはいけないと肝に銘じてください。

それだけ難しいのです。

http://naka.wankuma.com/site/column/dotnet/00001.htm
■No9574に返信(中博俊さんの記事)
>
> 弁さんが言うことを理解できていないのであればExcel操作はしてはいけないと肝に銘じてください。
>


あのやり方ですと、Excelが終了しないという問題が生じてしまうみたいですね・・・
もっと勉強して、後で出直します。
すみませんでした。
> Dim xlBook As Excel.Workbook = CType(xlApp.Workbooks.Ad, Excel.Workbook)
.Ad というのは .Add() の書き間違いだと思いますが、
いずれにせよNGです。
Workbooksコレクションも変数にとり、後で解放しましょう。

> xlBook = xlApp.Workbooks.Open(ファイルの保存先)
同様の理由でNGです.

というか、この xlBook には、すでに Workbooks.Add() で新規追加したブックが
格納されていますので、あらためて Openする必要が無い様な気もします。


> CType(xlBook.Sheets.Item("Sheet1"), Excel.WorkSheet).Range("A1").Value = TextBox1.Text

xlBook.Sheets.Item()もNG。
Range("A1").ValueもNG。


イメージ的には、
 xlBooks = xlApp.Workbooks
 xlBook = xlBooks.Open("C:\Book1.xls") または xlBooks.Add("C:\Book1.XLT")
 xlSheets = xlSheets.Open("Sheet1")
 xlSheet = xlSheets("Sheet1")
 xlRange = xlSheet.Range("A1")
 xlRange.Value = TextBox1.Text
 Marshal.ReleaseComObject(xlRange)
 Marshal.ReleaseComObject(xlSheet)
 Marshal.ReleaseComObject(xlSheets)
 xlBook.SaveAs(〜)
 Marshal.ReleaseComObject(xlBook)
 Marshal.ReleaseComObject(xlBooks)
 xlApp.Quit()
 Marshal.ReleaseComObject(xlApp)
って感じかな?
■No9580に返信(魔界の仮面弁士さんの記事)
> イメージ的には、
>  xlBooks = xlApp.Workbooks
>  xlBook = xlBooks.Open("C:\Book1.xls") または xlBooks.Add("C:\Book1.XLT")
>  xlSheets = xlSheets.Open("Sheet1")
>  xlSheet = xlSheets("Sheet1")
>  xlRange = xlSheet.Range("A1")
>  xlRange.Value = TextBox1.Text
>  Marshal.ReleaseComObject(xlRange)
>  Marshal.ReleaseComObject(xlSheet)
>  Marshal.ReleaseComObject(xlSheets)
>  xlBook.SaveAs(〜)
>  Marshal.ReleaseComObject(xlBook)
>  Marshal.ReleaseComObject(xlBooks)
>  xlApp.Quit()
>  Marshal.ReleaseComObject(xlApp)
> って感じかな?

ありがとうございます。

教えていただいた流れを元に、組んでみました。
>  xlSheets = xlSheets.Open("Sheet1")
の部分で、Openはxlsheetsのメンバではありませんとなってしまいましたので、どうしてよいのか分からず、xlBook.WorkSheetsとなっております。

しかし、問題点は解消されておりません。
何か抜けていたりするのでしょうか。

Dim xlApp As Excel.Application
Dim xlBooks As Excel.Workbooks = xlApp.Workbooks
Dim xlBook As Excel.Workbook = xlBooks.Open("C:\Book1.xls")
Dim xlSheets As Excel.Sheets = xlBook.Worksheets
Dim xlSheet As Excel.Worksheet = xlSheets("Sheet1")
Dim xlRange As Excel.Range = xlSheet.Range("A1")

xlRange.Value = TextBox1.Text

System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets)


Dim rlt As DialogResult
SaveFileDialog1.InitialDirectory = "C:\"
SaveFileDialog1.Filter = "エクセル形式(*.xls)|*.xls"
rlt = SaveFileDialog1.ShowDialog

If rlt = DialogResult.OK Then
xlBook.SaveAs(SaveFileDialog1.FileName)
ElseIf rlt = DialogResult.Cancel Then
Close()
End If

System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)

xlApp.Quit()


System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)

End Sub
プログラミング自体はまだまだ問題ありなのですが、ファイルの保存に関しては可能になりました。あとは、細かいところを調べていきたいと思います。

この件に関していろいろとレスを下さった方、ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板