• 締切済み

VB6.0 ExcelオブジェクトのFind操作について

VB6.0にてExcelよりデータの取り込み処理を 行っております。 その際に、ある指定の文字列が現れる最初の行を取得する 処理があるのですが、下記処理でインストールされている Excelのバージョンにより、エラーになってしまいます。 ====Excel2000の場合OK。 Excel2003の場合NG。===== '最終行を取得する。 Set ObjFR = .Columns(1).Find("終了") intMaxRow = ObjFR.Row ====Excel2003の場合OK。 Excel2000の場合NG。===== '最終行を取得する。 Set ObjFR = .Cells(1).Find("終了") intMaxRow = ObjFR.Row 上記、処理においてバージョンに依存せずに回避する方法が ありましたらお教え頂きたいと思います。 宜しくお願いいたします。

みんなの回答

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.9

ん、、伝わらないので、はっきり言いますね。 > 上記の場合でもColumnsをCellsにすれば動作します。 それはタマタマであって....バージョンに依存せずに回避する方法知りたいなら 偶然に依存するコードではダメだと思いますよ。 Find メソッドのヘルプを読みましたか? #8 に書きましたが、Find は見つからないと Nothing を返します。つまり、 Nothing 時のエラートラップが必要なので、明らかにエラーの原因は単純な コーディングミスです。 こういったメソッドの仕様について、#7 で示唆しているのだから > ColumnsをCellsにすれば動作します。 このような反証よりもまず、ヘルプを読むべきかと。そこに Nothing を返す ことも書いてあるのだから、それで解決するはずですけど... もう退散します。dsuekichi さん、お邪魔して申し訳ありません。

logigon
質問者

補足

>> ColumnsをCellsにすれば動作します。 >このような反証よりもまず、ヘルプを読むべきかと。そこに Nothing を返す >ことも書いてあるのだから、それで解決するはずですけど... 反証してるわけじゃないですけどね... ヘルプを見てNothingが返ることも分かっています。 ただ、Columns・Cellsの記述で動作する原因が分からないままだと 今後にも問題かと思いまして調査していました。 お忙しいところどうもありがとうございました

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.8

追加補足。 #7 に書いた様に、検索対象が違うなどが原因となって意図したセルが検索され ないケースは多いです。 このとき、「 Find は Nothing 」を返します。 また、 RangeObj.Find(~) としたときは、RangeObj の範囲で検索します。つまり、 With objExcelBook.Worksheets("シート名")   Set ObjFR = .Cells(1).Find("終了")   ~ End With は A1 セルだけ検索して終了しますので、A1 セルが「終了」でなければ、 Find は Nothing を返します。となると、ObjFR.Row は当然エラーです。

logigon
質問者

補足

上記Cellsの場合でObjFR.Rowが527(行数)という値が 取得できています。 Columnsにした場合、何を設定してもNothingが返ってきてしまいます。 記載しているプログラムは下記のとおりです。 '1 Set ObjFR = .Columns(1).Find(What:="終了", _ LookIn:=xlValues, _ LookAt:=xlWhole, _ SearchOrder:=xlByRows, _ MatchByte:=False) .Columns("A").Select '2 Set ObjFR = .Cells(1).Find(What:="終了", _ LookIn:=xlValues, _ LookAt:=xlWhole, _ SearchOrder:=xlByRows, _ MatchByte:=False)

  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.7

こんにちは。 > バージョンに依存せずに回避する方法.... 多分 Find の使い方が悪いのですよ。ヘルプを引用します。   --------------------------------------------------------------   引数 LookIn、LookAt、SearchOrder、および MatchByte の設定は、   このメソッドが使われるたびに保存されます。      次にこのメソッドを使うときに、これらの引数の指定を省略すると、   保存された設定が使われます。      これらの引数の設定を変更すると、[検索と置換] ダイアログボックス   に表示される設定が変わります。   -------------------------------------------------------------- したがって、Find の使い方は、 Set ObjFR = .Columns(1).Find(What:="終了", _                LookIn:=xlValues, _                LookAt:=xlWhole, _                SearchOrder:=xlByRows, _                MatchByte:=False)   ※注:参照設定してる場合のコードです。 みたいに面倒でも検索オプションを「明示的に指定」する必要があります。 つまり、環境が違えば、[検索と置換] ダイアログボックスに予め設定された 検索オプションが違う可能性がありますよね? 例えば、検索場所が「セル」だったり「数式」だったり。 上記のことを仮定すると、バージョンにより Find の結果が異なるように 見えた質問者、対して、通常一つの環境でしかテストしない回答者側では 再現しない...という行き違いが納得できるのですが、どうですか?

logigon
質問者

お礼

上記の場合でもColumnsをCellsにすれば動作します。 他にも要因があるのかもしれません。 もう少しこちらでも調査して見ます。 色々と有難う御座います。

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.6

・・・半分再現しました。 500行のExcelで Windows2000+Excel2000 WindowsXP+Excel2003 の環境で試してみました・・・ 結果、 > Set ObjFR = .Columns(1).Find("終了") は、Excel2000/Excell2003のどちらでもOK > Set ObjFR = .Cells(1).Find("終了") は、Excel2000/Excel2003のどちらもNG でした・・・ Excelのバージョン依存と言うより、データ依存の様な・・・ でも、使用しているデータは同じファイルなんですよね?

logigon
質問者

お礼

おっしゃるとおり、原因はデータ依存でした。 セルが結合されていたため、データが取得できていなかったようです。 お忙しいところ本当に有難う御座いました。

logigon
質問者

補足

同じExcelファイルです。 他端末(環境)でも調査してみます。

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.5

追記 ついでに > objExcelApp.DisplayAlerts = False も止めてみてください。 #他にも、通常動作を妨げる設定があるなら、全部一時的に止めてみてください。

logigon
質問者

補足

回答有難う御座います。 Excelの内容はA列の500行目に指定文字「終了」が記載されており、 他の行は一覧表(計画表)のように記載されている一般的な Excelシートです。 他処理でエラーは起きていないため、Error処理を止めても状況は 変わりません。 DisplayAlertsを止めても状況は変わりません。

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.4

> Excelファイルのセルの内容 こちらはどうなっていますか? 何列x何行のデータで、空白セル有りor無し、"終了"がどこのセルにある。 等でも良いです。 何か特徴がありますか? #行数が無茶苦茶多いとか、空白が多いとか・・・ > 上記のintMaxCnt = ObjFR.Rowでエラーになります。 > 「オブジェクト変数または With ブロック変数が設定されていません。」 これは、どうやって確認したんでしょうか? VB6を2台のPC(Excel2000がインストールされたPCとExcel2003がインストールされたPC)にインストールして、各々確かめた? それから、 > On Error GoTo ExcelErrHandler がありますが、これを止めたら、どうなります? #別の箇所でエラーになっていたりしませんか?

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.3

うーん。私の環境では再現しませんね・・・ #WindowsXP(SP2),Office2003(SP2),VB6(SP5) 再現試験をやってみたいんですが・・・ 差し支えない範囲でExcelファイルのセルの内容と、 実際のプログラムを提示できませんでしょうか? #余分な部分を削って、状況が発生するできるだけ短いコードで・・・ 後、Windowsのバージョンとか、SPの適用とかはどうなっていますか?

logigon
質問者

補足

すばやいご返答有難う御座います。 実際のプログラム(該当箇所まで)は下記になっています。 Dim objExcelApp As Object 'エクセルアプリ Dim objExcelBook As Object 'エクセルブック Dim ObjFR As Object Dim intMaxCnt As Integer 'オブジェクトの設定 Set objExcelApp = CreateObject("Excel.Application") Set objExcelBook = objExcelApp.Workbooks.Open("Excelファイルのパス") 'エクセルへ参照 On Error GoTo ExcelErrHandler '保存の確認ダイアログ非表示設定 objExcelApp.DisplayAlerts = False 'Excelを開く With objExcelBook.Worksheets("シート名") '最終行を取得する。 Set ObjFR = .Columns(1).Find("探索文字") intMaxCnt = ObjFR.Row End With 上記のintMaxCnt = ObjFR.Rowでエラーになります。 「オブジェクト変数または With ブロック変数が設定されていません。」 Windowsは2000,2003ともにXP SP2です。

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.2

> バージョンによって、ObjFRがNothingになってしまいます。 本当に、バージョンが原因ですか? 少なくとも、私のExcel2003では、ちゃんとHITします。 #Nothingにはなりません。 本当に、対象文字が無いのでは? 例えば、「HITするはずのセル」がCells(a,b)だとして、 > Set ObjFR = .Columns(1).Find("終了") の前で、 > MsgBox(.Cells(a,b)) とすると、「終了」とかが表示されますか?

logigon
質問者

補足

原因がバージョンかどうかは分かりませんが、 開発環境の違いは2003と2000の違いしか考えられません。 >> MsgBox(.Cells(a,b)) >とすると、「終了」とかが表示されますか? されます。 cellsとColumnsを変更すると正しく動作するので対象文字が 無い事はありません。

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.1

> ====Excel2000の場合OK。 Excel2003の場合NG。===== > '最終行を取得する。 > Set ObjFR = .Columns(1).Find("終了") > intMaxRow = ObjFR.Row Excel2003で実行してみましたが・・・エラーにはなりませんけど・・・ ちなみに、「.Columns(1)」の前は(多分Withで指定しているはずですが)何なのでしょう? ちゃんと、該当Sheetを指定していますか?

logigon
質問者

補足

早速のご返答ありがとうございます。 With objExcelBook.Worksheets("シート名") でシートの記述を行っています。 バージョンによって、ObjFRがNothingになってしまいます。

関連するQ&A

  • VBとExcelオブジェクト

    VB6から 起動してまたは→CreateObject ("Excel.Application") オープン中の→GetObject(, "Excel.Application") Excelのデータを取り込んでいるのですが エクセルのデータが一定以上の行を超えると エクセルがタスクに残ってしまいます。 過去ログなどを見ましたがいまいち原因がつかめません。 使っているのは、Rangeぐらいしかありません。 現状は、取込範囲が 44行でアウト 40行はOKといった感じです。 複雑なことはやっていませんが 取り込む行数によって現象が 起こったり起こらなかったりして 困っています。 ************************************ プログラム概要 GetObject版 Dim objExcel As Excel.Application Dim SheetNm As String Set objExcel = GetObject(, "Excel.Application") SheetNm = objExcel.ActiveSheet.Name Do Until 縦=終了条件    Do Until 横=終了条件           構造体.XXX = objExcel.Range(座標).Value       横=横+1    Loop    縦=縦+1 Loop Set objExcel = Nothing    .    .    . 格納した構造体のデータをデータベースに格納    .    .    . ************************************ CreateObjectの場合は、 openやclose、Quitも記述してあります。

  • VBからExcelを操作

    VisualBasic6.0(初心者) VBを始めたばかりで、Excelの入力文字をVBで変換しようと考えています。 様々な保管場所にあるExcelを開いて選択セルの文字をコマンドボタンで変換しようと下記コードを考えました。(一部) 問題は、Load時にすでに開いているExcelを閉じてまいます。 何か良い方法は無いでしょうか?(アクティブなExcelを操作したい) また、下記コードで不適切なところがありましたら御教授願います。 Private Sub Form_Load() Dim xlApp As Excel.Application Dim xlBook As Excel.Workbook Dim xlSheet As Excel.Worksheet Set xlApp = CreateObject("Excel.Application") Set xlBook = xlApp.Workbooks.Add Set xlSheet = xlBook.Worksheets(1) Set xlApp = GetObject(, "Excel.Application") With xlApp.Selection Cells(1, 1).Value = "" End With xlApp.DisplayAlerts = False xlApp.Quit Set xlSheet = Nothing Set xlBook = Nothing Set xlApp = Nothing End Sub '----------------------(大文字変換) Private Sub CB2_Click() On Error Resume Next If ActiveCell.Row = Null Then MsgBox "Excel が見つかりません" Else Dim xlApp As Excel.Application Set xlApp = GetObject(, "Excel.Application") If Err.Number Then MsgBox "Excel が起動されていません" Else Dim X As Long Dim Y As Long Dim Hmae As String Dim Hgo As String X = 0 Y = 0 With xlApp.Selection Do Do Hmae = Cells(ActiveCell.Row + X, ActiveCell.Column + Y).Value Hgo = StrConv(Hmae, 1) Cells(ActiveCell.Row + X, ActiveCell.Column + Y).Value = Hgo X = X + 1 Loop Until X >= .Rows(.Rows.Count).Row - .Row + 1 X = 0 Y = Y + 1 Loop Until Y >= .Columns(.Columns.Count).Column - .Columns(1).Column + 1 End With End If xlApp.DisplayAlerts = False Set xlApp = Nothing End If End Sub

  • VB6.0上でExcelオブジェクトを生成

    質問です。 VB6.0上でExcelオブジェクトの生成についてです。 その1 Dim xlApp As Excel.Application … Set xlApp = CreateObject("Excel.Application") と その2 Dim xlApp As Object … Set xlApp = CreateObject("Excel.Application") と、どちらが良いのでしょうか? 開発環境は Win XP SP2 VB 6.0 Excel 2003 実行環境は Win 98 SE VB 6.0(ランタイムのみ) Excel 2000 SR-1 です。 開発環境ではその1、その2ともOKなのですが、 実行環境ではその2のみがOKです。 参考書にはその1が書かれていますが、その2を使うことによって何か不具合や都合の悪いことが起こりうるのでしょうか? あるいは当方の見当違いで根本的に何かが間違っているのでしょうか? どんな些細なことでも結構ですので宜しくお願いします。

  • Access からオブジェクトとして開いたExcelのプロセスが終了しない

    AccessからExcelのデータを読み込んだ後、Accessを終了させてもプロセスが終了しません。 bookはclose、applicationはquit、オブジェクト変数はnothingというExcelの終了記述をしているので他の問題なのかと思いいろいろ調べて試しましたが解決できません。 Excelのファイル名とシート名はAccessのフォームに貼り付けたテキストボックスの値を取得させていますが下記コードでは省略しています。環境はWin2000Server、Access2000です。 どなたかお気づきの点があればどうぞご教授お願いします。 --------------------------------- Public Sub test() Dim filename As String Dim sheetname As String filename = "c:\パス\ファイル名.xls" sheetname = "シート名" 'AccessからExcelをオブジェクトとして開く Dim xlApp As Object Dim xlBook As Object Dim xlSheet As Object Set xlApp = CreateObject("Excel.Application") Set xlBook = xlApp.Workbooks.Open(filename) Set xlSheet = xlBook.Worksheets(sheetname) 'Excelの行取得用変数設定 Dim xlrow As Integer 'データ開始行 xlrow = 5 Dim xlrowEnd As Integer 'データ最終行(最終行は合計値が入っているので-1とする) xlrowEnd = (Range("A5").End(xlDown).Row) - 1 'Excelデータの取り込み Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection Set rs = New ADODB.Recordset rs.Open "a", cn, adOpenKeyset, adLockOptimistic cn.Execute "delete * from a" xlrow = 5 'Excelデータの開始行番号 Do While xlrow <= xlrowEnd rs.AddNew rs!フィールド1 = xlSheet.Cells(xlrow, 1).Value rs!フィールド2 = xlSheet.Cells(xlrow, 2).Value rs.Update rs.MoveNext xlrow = xlrow + 1 Loop 'Excelの終了記述 xlBook.Close xlApp.Quit Set xlSheet = Nothing Set xlBook = Nothing Set xlApp = Nothing 'ADO接続終了記述 rs.Close Set rs = Nothing cn.Close Set cn = Nothing

  • EXCEL2000、VBAのFindメソッドの仕様(1行目の取扱)について

    EXCEL2000のVBAでマクロを作っています。 Sheet1のA列に下記の様に数字を入れ、作成したfindcheckのマクロを実行します。検索値の5は一番最初に1行目に現れるので、メッセージボックスによって1と表示されるはずなのですが、4と出ます。 おかしいなぁと思って4行目の5を別の数字にするとメッセージボックスで1が表示されるようになりました。いろいろ検索してみると、フィルタなどでは1行目はタイトルとして扱われる…みたいな記述があったので、この場合も1行目は特別な意味を持つのかなぁと思い質問しました。 今回は検索結果が複数ある場合、1番最初に出たセルの行数を表示したいと思っています。1行目を「数値一覧」として、列タイトルの様にしたところ、うまくいきそうでした。もしこの動作が仕様なのかどうかご存じの方がいらっしゃったら教えていただきたいと思います。 どうぞよろしくお願いします。 ■Sheet1のA行目の数字 ----------------------------------------------------------- 5 3 2 5 4 3 2 1 1 ----------------------------------------------------------- ■VBAのコードサンプル ----------------------------------------------------------- Sub findcheck() Dim searchResult As Range Set searchResult = Worksheets("Sheet1").Columns("A").Find("5") If searchResult Is Nothing Then MsgBox "見つかりません" Else MsgBox searchResult.Row End If End Sub -----------------------------------------------------------

  • VB.NET2003のDataGridでコンボボックス

    こんにちは。 最近VB.NET(2003)を始めたばかりの初心者です。 DataGridにコンボボックスを作成する方法を探してまして、 http://dobon.net/vb/dotnet/datagrid/datagridcombobox.html に書いてあるようにDataGridTextBoxColumnクラスからの派生クラスを作成して呼び出してみました。 そうしたところ、コンボボックスが表示され、データのセットもきちんとできました。 しかし、そのコンボボックスで選択している値を取得する方法がわからなく困ってます。 たとえば Dim comboSorce As New DataTable("ComboBox") comboSorce.Columns.Add("DisplayMember", GetType(String)) comboSorce.Columns.Add("ValueMember", GetType(Integer)) comboSorce.Rows.Add(New Object() {"OK", 0}) comboSorce.Rows.Add(New Object() {"NG", 1}) というデータをコンボボックスにセットした場合 OK,NGという表示上の値は CStr(DataGrid1(row,col)) で取得できますが、実際の値を取得する方法がわかりません。 ご存知の方いらっしゃいましたら、ご教授ください。 それと、行毎に違う値(リストデータ)のコンボボックスを作成することはできますでしょうか? 以上です。よろしくお願いします。

  • マクロセルの値によってセルの色を消す

    エクセル2013です。 セルの値が0又は空白の場合でそのセルが色塗りされていたら色を消す というマクロをを作成しました。 ただ700行55列では処理が遅いです。 Sub 色消() '成功 Dim 最終行 Dim 最終列 Dim 対象セル As Range 最終列 = Cells(8, Columns.Count).End(xlToLeft).Column '8行目の最終列を取得 最終行 = Cells(Rows.Count, 1).End(xlUp).Row 'A列の最終行を取得 For Each 対象セル In Range(Cells(10, 17), Cells(最終行, 最終列)) If 対象セル.Value = 0 Or 対象セル = "" Then 対象セル.Interior.ColorIndex = 0 End If Next 対象セル End Sub 対象範囲から対象セルを全部見つけて一括処理すれば早いのではと 以下のマクロを作成してみましたが Set 対象範囲 = Cells.Find(What:=0 Or "", LookIn:=xlValues, LookAt:=xlWhole) で構文ERRです。 どこを直せばいいのでしょうか? よろしくお願いします。 Sub 色消2() '2014/8/4 '失敗 Dim 対象範囲 Dim 最終行 Dim 最終列 最終列 = Cells(8, Columns.Count).End(xlToLeft).Column '8行目の最終列を取得 最終行 = Cells(Rows.Count, 1).End(xlUp).Row 'A列の最終行を取得 対象範囲 = Range(Cells(10, 17), Cells(最終行, 最終列)) Set 対象範囲 = Cells.Find(What:=0 Or "", LookIn:=xlValues, LookAt:=xlWhole) If Not 対象範囲 Is Nothing Then 対象範囲.Interior.ColorIndex = 0 End If End Sub

  • シートをオブジェクト変数に格納しつつ、findで文

    前回、http://okwave.jp/qa/q7965940.html で質問したのですが、 シートをオブジェクト変数に格納しつつ、findで文字を検索する場合、どうすればいいでしょうか? Sub test() Dim sh1 As Worksheet Dim 行 As Long Set sh1 = Sheets("Sheet1") 行 = Cells.Find(What:="検索文字", LookAt:=xlWhole).Row End Sub こういう事を行いたいのですが、 Sheet2がアクティブな時にこのコードを実行すると実行時エラー91になります。 対処方法をお願いいたします。

  • VBでExcelオブジェクトを引数を渡して起動させたい

    VBからExcelオブジェクトを起動させて帳票を印刷するPGを作成しています。 起動するExcelオブジェクトのVBAの関数に引数を渡したいのですが、 可能でしょうか?方法を知っている方がいらっしゃいましたらどうか教えて 下さい。よろしくお願い致します。 参考までに今私が書いたコードを表示しておきます。 ' Excel オブジェクト生成 Set objExcel = New Excel.Application ' 作業期間日付の取得 sSdate = txtDate.Text '開始日 sEdate = CStr(DateAdd("d", 6, CDate(sSdate))) ' 終了日 ' アイコンを砂時計にする Screen.MousePointer = vbHourglass '列が存在している場合は確認メッセージ If MsgBox(sSdate & "~" & sEdate & "の期間を印刷してよろ しいですか?", vbOKCancel, sTitle) = vbCancel Then GoTo ExitFunc End If '*********** ' 印刷処理 '*********** Call objExcel.Workbooks.Open(ファイルのパス) Call objExcel.Run("Main") このような感じです。変数sSdateとsEdateをMainに渡したいと考えています。

  • Excel2013にしたらVBAがすごく重くなった

    会社のPCがExcel2010からExcel2013に変更されたのですが、Excel2010の環境で作成していたVBAマクロの処理がもの凄く遅くなってしまいました。 Excel2010では10秒ほど待てば終わった処理が30分以上かかるようになってしまい、業務効率を上げるために作ったVBAが逆に非効率になってしまい困っております。 (フリーズしたような感じになりますが、長時間までは処理は終わり、エラーは出ておりません) Excel2013で重くなった箇所を調べていたら、下記コード部分の繰返し処理で重くなっているのが分かりました。 処理の概要は、「全体」シートの指定列の最終行のセルから指定された番号(12345)があるか1行ずつ調べていき、ヒットしたらその行を全体を切取り、「●●」シートの最終行に貼り付けていく単純なものです。 「全体」シート行数は8000~10000行あります。 ・重くなっている処理の箇所 ================================== Application.ScreenUpdating = False ActiveWorkbook.Worksheets("全体").Activate LastRow = Cells(Rows.Count, 1).End(xlUp).Row For i = 1 To LastRow If Cells(i, 5).Value Like "12345" Then Rows(i).Cut Sheets("●●").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) End If Next i ================================== Excel2010で問題のなかった処理がExcel2013になって途端に重くなった原因自体も分かりませんが、問題点の回避方法や処理速度を改善する方法はありませんでしょうか。 よろしくお願いいたします。

専門家に質問してみよう