tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトルVB6でEXCELのソート
記事No14301
投稿日: 2009/11/26(Thu) 21:36
投稿者困った人
VB6でEXCELオブジェクトを使用して一旦できたファイルの整形を
おこなっております。
その際にソートもいれようと思ったのですが、EXCELオブジェクトで
どのように作っていいかわからなかったので、あるEXCELで
マクロの記録を使ってソートのマクロを記録で作り以下のように
(下記の)START,ENDのところのようににコピペしたところ、1回目はうまく
いきますが、2回目以降はCellsメソッドは失敗しました。
というエラーがでます。
このエラーをおこさずに何度でもリトライできる方法を教えてください。
目的は、簡単に3,4,5列目を簡単にソートしたいだけです。2行目から。

環境 VB6(SP6)
OS WIN XP
備考 参照設定 EXCEL 11object liblaly
<以下PG>

Private Function SetExcelLayout_umpn() As Boolean
Dim objExcel        As Object
Dim objBook         As Object
    On Error GoTo Err_SetExcelLayout_umpn
    SetExcelLayout_umpn = False

    'Excelを起動
    Set objExcel = CreateObject("Excel.Application")
    Set objBook = objExcel.Workbooks.Open(txtExcelPath.Text)
    With objBook.Sheets(objBook.Sheets(1).Name)
        '列幅の設定
        .Columns("A:D").ColumnWidth = 8.38
    End With
'----START
    Cells.Select
    Selection.Sort Key1:=Range("C2"), Order1:=xlAscending, Key2:=Range("D2") _
        , Order2:=xlAscending, Key3:=Range("G2"), Order3:=xlAscending, Header:= _
        xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
        SortMethod:=xlPinYin, DataOption1:=xlSortTextAsNumbers, DataOption2:= _
        xlSortTextAsNumbers, DataOption3:=xlSortNormal
    objBook.Save
'----END
Err_SetExcelLayout_umpn:
'略
End Function

[ツリー表示へ]
タイトルRe: VB6でEXCELのソート
記事No14302
投稿日: 2009/11/26(Thu) 22:47
投稿者花ちゃん
ここで質問されるなら、ここに書いてある、[Excel & Word 関係]に書いてある事位は、
見てから質問するようにして下さい。

[Excel & Word 関係] の一番最初の項の
VBからExcel及びWordを操作する時の注意事項 や
Excel のタスクを正常に終了できない現象 や
エクセル!ワンポイントテクニック集(その1)の中の 1.並べ替え (1) 等を。

又、サンプル投稿用掲示板の
Excel 操作ワンポイントテクニック集(VB6.0 基本編)
Excel 操作ワンポイントテクニック集(VB6.0 応用編)

[ツリー表示へ]
タイトルRe: VB6でEXCELのソート
記事No14303
投稿日: 2009/11/26(Thu) 23:17
投稿者魔界の仮面弁士
> Dim objExcel        As Object
> Set objExcel = CreateObject("Excel.Application")
レイトバインドでの実装を行っているようですね。

では一度、Excel への参照設定を外してコンパイルしてみてください。
その状態で、定数(xlAscending等)以外がエラーになるようであれば、
その箇所に、コーディング上の記述ミスがある事になります。


> このエラーをおこさずに何度でもリトライできる方法を教えてください。
http://hanatyan.sakura.ne.jp/vbhlp/excelframe.htm
の「(最初に必ずお読み下さい)」「(こちらも合せてお読み下さい)」をご覧下さい。


>     'Excelを起動
>     Set objExcel = CreateObject("Excel.Application")
ここで、Excel を一つ起動していますね。

>     Set objBook = objExcel.Workbooks.Open(txtExcelPath.Text)
そしてここでは、その起動したExcelの Workbooks を操作しています。

> '----START
>     Cells.Select
では、ここでいう「Cells」とは、どの Excel のどのブック上のセルでしょうか?

「objBook.Workbooks(1).Cells.Select」などであれば、最初のワークシート上の
全セルを選択状態にする、という事が明らかになります。

しかし単に「Cells.Select」と書いただけでは、どのオブジェクトを操作するかが
曖昧になってしまっているわけです。Excel VBA であれば、自シート上のセルで
ある事が明らかですが、外部(VB6)から操作する場合はそうはいきません。


なお、VB6 から Excel を参照設定しておらず、しかも Option Explicit の場合には、
「Cells.Select」だと、Cells が“変数は宣言されていません”のエラーになります。
しかし「〜.Cells.Select」として、どのオブジェクトを操作しているのかを
正しく記述していれば、そうしたコンパイルエラーが発生する事もありません。
(なので、参照設定をあえて外す事も、問題点の発見の役に立ちます)


分かりにくいのは、今回のように Excel を参照設定していた場合ですね。
親オブジェクトを記述していない“間違ったコード”であっても、初回実行時には
グローバルオブジェクト経由で操作できてしまうのですが、Excel を起動しなおすと、
最初に起動していた方と、二回目の Excel のうち、どちらを操作するのかが曖昧に
なってしまい、問題が生じるわけです。また、このようなコードは、アプリ終了後も
非表示の Excel プロセスが解放されずに残ってしまうなどの弊害を伴います。

親オブジェクトを明示し、曖昧さを排除すれば、参照設定の有無に関わらず、
問題無く動作するようになります。


>     Selection.Sort Key1:=Range("C2"), Order1:=xlAscending, Key2:=Range("D2") _
>         , Order2:=xlAscending, Key3:=Range("G2"), Order3:=xlAscending, Header:= _
>         xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
>         SortMethod:=xlPinYin, DataOption1:=xlSortTextAsNumbers, DataOption2:= _
>         xlSortTextAsNumbers, DataOption3:=xlSortNormal
こちらも同様です。

「Selection」が、どのオブジェクトの選択領域を指しているのか、
「Range」が、どのブック上の範囲を示しているのか示されていません。

たとえば、Range("C2") ではなく、〜.Range("C2")。
Selection ではなく、objExcel.Selection などのように、
曖昧さを無くす記述をすれば、今回の問題は解決するはずです。


ただし、さらに言えば、そもそも Select や Selection を使ったコードを
多用するべきではありません。マクロ操作で自動生成されるコードでは、
まず選択ありきなので仕方無いのですが、VB にするときはシート名や範囲名を
明示したり、それらを変数で受けて利用する事を心がけてください。


たとえば普段、VB6 の操作でも
 Form2.Text1.Text = "TEST"
などとは書いても、
 Form2.SetFocus
 Screen.ActiveForm.Text1.SetFocus
 Screen.ActiveControl.Text = "TEST"
なんて書き方はしませんよね。

それと同じことで、
 objSheet1.Cells.Select
 objExcel.Selection.Sort Key1:=objSheet1.Range("C2"), 〜
などと書く必要は無く、
 objSheet1.Cells.Sort Key1:=objSheet1.Range("C2"), 〜
あるいは
 objSheet1.Cells.Sort objSheet1.Range("C2"), 〜
などと直接書けば済むという事です。

[ツリー表示へ]