人に聞けない痔の悩み、これでスッキリ >>

おはようございます。
VB6.0使ってます。
よろしくお願いします。

csvファイルの項目数を数えたいのですが、新・旧レコードの2つが混ざっており、項目数も違います。項目にはデータだけでなく空もあります。

例:
001,suzuki,19800101,,tokyo,F
002,tanaka,19800202,A

新は項目が6あるが
旧は4つしかない。
時々、項目には空も混ざっている。
For文で数えてみようとしたのですが、旧だと項目数が足りないので数えられないですねf^^;
同様に6番目があるかないかとかアホウなことも考えましたがこれも無理でした。

アドバイス、ヒント、ツッコミ、よろしければお願いいたします。

A 回答 (4件)

Splitを使うと、カンマ区切り(その他でもできますが)のデータを


分解することができます。
分解したデータを格納した配列の要素数を取得すれば、項目数がわかるのでは?
参考までに、以下にサンプルとしてコードを記します。
(エラー処理などは特につけてません。)
ミスがあったらごめんなさい('';)

Public Sub ReadFile()
Dim strFilename As String
Dim intFileNo As Integer
Dim blnOpenFlg As Boolean
Dim vntBuf As Variant
Dim strBuf As String
Dim lngCnt As Long
Dim lngDataCnt As Long

'初期値設定
blnOpenFlg = False

'ファイル名設定
strFilename = "C:\TEST.csv"
intFileNo = FreeFile()

'ファイルオープン
Open strFilename For Input As #intFileNo
'ファイルオープンしたらフラグOn
blnOpenFlg = True

lngCnt = 1
Do While Not EOF(intFileNo)
'データを一行単位で読込
Line Input #intFileNo, strBuf
'Splitをつかって、取り出した文字列を分解
vntBuf = Split(strBuf, ",")
'要素数を取得
lngDataCnt=uBound(vntBuf)+1

MsgBox Cstr(lngcnt) & "行目の項目数は" & Cstr(lngDataCnt) & "個です。"

lngCnt = lngCnt + 1
Loop


'ファイルを閉じる
If blnOpenFlg = True Then
Close #intFileNo
blnOpenFlg = False
End If

End Sub

この回答への補足

この場をお借りしてお礼を言わせて頂きます。
皆様のおかげで出来上がりました(^-^)
ポイントは均等に入れたいところですが、#2と#4の方をメインにブレンドして作らせていただいたので今回はお二方にポイントを入れておきます。
本当にありがとうございました(^-^)

補足日時:2006/09/07 09:44
    • good
    • 0
この回答へのお礼

お返事ありがとうございます!
おお、VBにもsplitあったんですね!
Javaを少ししていたので知ってはいたのですが…
VBにもsplitが…
あ、借りたVBの本が4.0でした!
そりゃ載ってねえって話ですよねf^^;

お礼日時:2006/09/07 09:44

s_husky です。



ErrMessage()は無関係でした。
ライブラリを余分にコピーしていました。
    • good
    • 0

項目数ですと、次のようにして求めることが可能です。



Private Sub コマンド0_Click()
  Dim I    As Integer
  Dim N    As Integer
  Dim Datas() As String
  
  Datas() = FileReadArray("c:\temp\vbtest.csv")
  N = UBound(Datas())
  For I = 0 To N
    MsgBox CharCount(Datas(I), ",") + 1
  Next I
End Sub

なお、ここでは、FileReadArray()、CharCount()関数を利用しています。

Public Function FileReadArray(ByVal FileName As String) As String()
On Error GoTo Err_FileReadArray
   Dim fso    As FileSystemObject
   Dim fil    As File
   Dim txs    As TextStream
   Dim strText  As String
   Dim strTexts() As String
  
   Set fso = New FileSystemObject
   Set fil = fso.GetFile(FileName)
   Set txs = fil.OpenAsTextStream(ForReading, TristateUseDefault)
   strText = txs.ReadAll
   strTexts = Split(strText, Chr$(13) & Chr$(10))
Exit_FileReadArray:
   FileReadArray = strTexts()
   Exit Function
Err_FileReadArray:
   MsgBox Err.Description & "(FileReadArray)", vbExclamation, " 関数エラーメッセージ"
   strTexts() = Split("")
   Resume Exit_FileReadArray
End Function

Public Sub ErrMessage(ByVal CnnErrors As ADODB.Error, ByVal strSQL As String)
   MsgBox "ADOエラーが発生しましたので処理をキャンセルします。" & Chr$(13) & Chr$(13) & _
      "・Err.Description=" & CnnErrors.Description & Chr$(13) & _
      "・Err.Number=" & CnnErrors.Number & Chr$(13) & _
      "・SQL State=" & CnnErrors.SQLState & Chr$(13) & _
      "・SQL Text=" & strSQL, _
      vbExclamation, " ADO関数エラーメッセージ"
End Sub

Public Function CharCount(ByVal Text As String, ByVal C As String) As Integer
  Dim I As Integer
  Dim L As Integer
  Dim N As Integer
  
  L = Len(Text)
  For I = 1 To L
    N = N + Abs(StrComp(Mid$(Text, I, 1), C, vbTextCompare) = 0)
  Next I
  CharCount = N
End Function
    • good
    • 0
この回答へのお礼

お返事ありがとうございます!
UBoundで上限値返せば早いですねー!
すっかり忘れていたましたf^^;

お礼日時:2006/09/07 09:43

ちょっと正式なやり方がわからないのですが、俺だったら1行丸ごと読み込み","の数を数えます。


後は応用で何とかなるかな?と思います。
サンプルプログラムとして、
Open "test.csv" For Input As #1
Line Input #1, l_in
Close #1
cnt = 0
text_len = 0
Do
text_len = InStr(text_len + 1, l_in, ",")
cnt = cnt + 1
Loop While (text_len > 0)
Label1.Caption = cnt
    • good
    • 0
この回答へのお礼

お返事ありがとうございます!
なるほどー!カンマを数えれば早いですね!
InStrはそういえばあったような…

お礼日時:2006/09/07 09:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QEXCEL VBA で現在開いているブックのファイル名を取得する方法

EXCEL2003 VBAで業務を簡素化するために、現在開いているブックのファイル名を取得する方法が分かりません。
作業手順をマクロを使って処理していますが、オリジナルのワークブックをファイル名を変えて保存し、以後、このワークブックを読み込んで使用しています。
このときのVBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり、以後の業務に使用できません。
常にファイル名を取得出来るVBAをどなたか、教えて下さい。

Aベストアンサー

>現在開いているブックのファイル名
 ちょっと曖昧な表現かなぁという気もいたしますが、VBAが書いてあるブックのブック名は
ThisWorkbook.Name
で、現在 "アクティブにして" 操作対象になっているブックの名前は
ActiveWorkbook.Name
ですね。

 しかし、
>VBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり
というような文脈からすると、
ThisWorkbook.Name
の方ですかね。

QEXCEL VBAマクロ作成で、他のEXCELからデータを取り込みたい

メインプログラム(EXCEL VBA)より、
他のフォルダーにあるEXCELの項目の内容を取り込みたいです。
たとえば他のフォルダーのEXCELのRange("A2:A3").ValueをメインプログラムのRange("C2:C3").Valueにセットしたい時です。

・コマンドボタン押したら、どこのEXCELから取り込むかのポップアップ(?)は、表示はできてます。
・作業者が選んだパスとブックもMsgBoxで表示できてるので、もらう相手の場所も取得できてます。

・となると次はOPEN,INPUTですか?
テキストデータの取り込みですと、Inputでそのバッファを定義してるのですが、なんか違うような。。。

よろしくお願いします!

Aベストアンサー

私がやる方法です。

Dim writeSheet As Worksheet ' 自分自身の書き出し先シート
Set writeSheet = ThisWorkbook.Worksheets(1) ' Sheet1 を参照

Dim readBook As Workbook ' 相手ブック
Set readBook = Workbooks.Open(filename) ' 相手ブックを開いて参照
Dim readSheet As WorkSheet ' 相手シート
Set readSheet = readBook.Worksheets("sheetName") ' 相手シートを参照
' または Set readSheet = readBook.Worksheets(sheetIndex)

' 例えば
writeSheet.Cells(1, 1).Value = readSheet.Cells(2, 2).Value ' 相手シートの B2 の値を自分自身の A1 に書き込む

readBook.Close False ' 相手ブックを閉じる
Set readSheet = Nothing
Set readBook = Nothing

私がやる方法です。

Dim writeSheet As Worksheet ' 自分自身の書き出し先シート
Set writeSheet = ThisWorkbook.Worksheets(1) ' Sheet1 を参照

Dim readBook As Workbook ' 相手ブック
Set readBook = Workbooks.Open(filename) ' 相手ブックを開いて参照
Dim readSheet As WorkSheet ' 相手シート
Set readSheet = readBook.Worksheets("sheetName") ' 相手シートを参照
' または Set readSheet = readBook.Worksheets(sheetIndex)

' 例えば
writeSheet.Cells(1, 1).Value = readSheet.Ce...続きを読む

Q【VBA】ExcelマクロでCSVファイルに保存したデータが""で囲まれてしまう

添付図のような、Excel2003で作成した表内のデータを
CSVで保存するマクロを作成したのですが、
図のように、CSVファイルに「""」で値が囲まれた状態で、
保存されてしまいます。

下記にマクロを記載しますので、
どうすれば文字列が「""」で囲まれずに、
カンマ区切りだけのデータで出力されるのか、
ご存知の方おられましたら、ご教示お願い致します。

Sub csv保存()
Dim フォルダ名 As String
Dim パス名 As String
Dim ファイル名 As String
Dim データ As Variant
Dim 行数 As Long, 列数 As Integer
Dim i As Integer, j As Long, k As Long

ファイル名 = "test.csv"
フォルダ名 = "csv"
パス名 = ActiveWorkbook.Path & "\" & _
フォルダ名

'csvフォルダが存在しなければ作成する
If Dir(パス名, vbDirectory) = "" Then
MkDir パス名
End If
ChDir パス名

Open ファイル名 For Output As #1

For i = 1 To Worksheets.Count
Worksheets(i).Activate
Worksheets(i).Cells(1, 1).Select
ActiveCell.CurrentRegion.Select
行数 = Selection.Rows.Count
列数 = Selection.Columns.Count

For j = 1 To 行数
For k = 1 To 列数 - 1
データ = Selection.Cells(j, k) _
.Value
Write #1, データ;
Next k
Write #1, Selection.Cells(j, 列数) _
.Value
Next j
Next i
Close #1
End Sub

添付図のような、Excel2003で作成した表内のデータを
CSVで保存するマクロを作成したのですが、
図のように、CSVファイルに「""」で値が囲まれた状態で、
保存されてしまいます。

下記にマクロを記載しますので、
どうすれば文字列が「""」で囲まれずに、
カンマ区切りだけのデータで出力されるのか、
ご存知の方おられましたら、ご教示お願い致します。

Sub csv保存()
Dim フォルダ名 As String
Dim パス名 As String
Dim ファイル名 As String
Dim データ As Variant
Dim ...続きを読む

Aベストアンサー

Write # は文字列を""で囲んで出力する仕様になっています。
そのまま出力したければ、Print #を利用すればよろしいかと。
ただし、Printの場合は区切り文字(カンマ)を自動で出力してくれませんので、併せて出力する必要があります。

For j = 1 To 行数
  For k = 1 To 列数 - 1
    データ = Selection.Cells(j, k) .Value
    Print #1, データ; ",";
  Next k
  Print #1, Selection.Cells(j, 列数).Value
Next j

なお、いらぬおせっかいですが、ドライブが複数ある環境下だと、
 ChDir パス名
だけでは必ずしもcvsフォルダ内に、ファイルが作成されるとは限りません。
 Open パス名 & "\" & ファイル名 For Output As #1
のように、フルパスで指定しておいた方が確実かと…

QEXCELファイルのカレントフォルダを取得するには?

EXCELファイルのカレントフォルダを取得するには?

C:\経理\予算.xls

D:\2005年度\予算.xls

EXCEL97ファイルがあります。

VBAで
  カレントフォルダ名
(C:\経理\,D:\2005年度\)
を取得する事は可能でしょうか?

CURDIRでは上手い方法が見つかりませんでした。

Aベストアンサー

こんばんは。
Excel97 でも、同じですね。以下で試してみてください。

Sub test()
'このブックのパス
a = ThisWorkbook.Path
'アクティブブックのパス
b = ActiveWorkbook.Path
'Excelで設定されたデフォルトパス
c = Application.DefaultFilePath
'カレントディレクトリ
d = CurDir
MsgBox "このブックのパス   : " & a & Chr(13) & _
   "アクティブブックのパス: " & b & Chr(13) & _
   "デフォルトパス    : " & c & Chr(13) & _
   "カレントディレクトリ : " & d & Chr(13)
End Sub

Q【VBA】テキストファイルを指定行数からの読み込み

こんばんは。

EXCEL VBAでテキストファイルを読み込む事について質問です。

VBAでテキストファイルをこちらから指定する行数(上から何番目という感じで)からデーターを読み込みたいのですが、どの関数をつかっていいかわからず困っています。
1行ずつ読みこむ「Input Line関数」では、無駄な行まで読み込むので動作が遅くなります。
読み込みたい行はすでにわかっているので、最初からその行に飛んでからデーター読み込みたいと思ってます。

ちなみに指定する行数は、ファイルによって違います。
あらかじめ「Input Line関数」で、ある文字が何行目にあるかを探す行為をあらかじめ行っています。

みなさまのアイデアを拝借したく、よろしくお願いします。

Aベストアンサー

速度は分かりませんが、これとか
http://officetanaka.net/excel/vba/filesystemobject/textstream10.htm

あるいは、丸ごと読みこんで、改行コードでSplitして、文字列配列を相手に該当行検索も含めて処理するとか。
昨今のPCでは、相当大きなテキストファイルでもメモリー内で処理できると思います。
http://officetanaka.net/excel/vba/filesystemobject/textstream07.htm

テキストファイルの構造によってはADOで処理する案も考えられますが、Recordsetにはファイルの先頭から(あるいは末尾先頭で)入っている事が保証されているのか、ちょっと心配。参考URLはCSVになっていますが、タブ区切りテキストファイル(拡張子.txt)でもいけます。
http://home.att.ne.jp/zeta/gen/excel/c04p47.htm

以上ご参考まで。

QEXCEL VBAで計算値を四捨五入、切り上げ、切捨てする方法

ネットで探してみたのですが、計算結果を四捨五入して特定のセルを
返すにはどうしたらいいのでしょうか?

Sub hokangosa()

Dim ZPS As Double
Dim ZPOS As Double
Dim DMN As Double
MsgBox (" >>> 補間誤差自動計算 <<< ")
MsgBox (" >>> 初期値入力します <<< ")
ZPS = InputBox(">>> ステップを入力してください<<<")
ZPOS = Sheet1.Cells(22, 4).Value
DMN = ZPOS / ZPS
Sheet1.Cells(23, 6).Value = DMN
End Sub

ここでDMNの値を四捨五入したいです。

またこれとは別に切上げ、切捨ても教えていただけるとありがたいです。

Aベストアンサー

DMN = Application.WorksheetFunction.Round(ZPOS / ZPS, 0)
で、四捨五入
DMN = Application.RoundDown(ZPOS / ZPS, 0)
で切り捨て
DMN = Application.RoundUp(ZPOS / ZPS, 0)
で切り上げです。

引数で、対象桁を変更できます。

Q【Excel VBA】マクロでExcel自体を終了させたい

環境:WindowsXP、Excel2003

マクロでエクセルを終了(ブックを閉じて、アプリケーション自体も終了)させたいのですが、以下のコードではアプリケーションが閉じてくれません。

ThisWorkbook.Close
ExcObj.Quit
Application.Quit

どこか悪いところはありますでしょうか?

よろしくお願いします。

Aベストアンサー

普通に考えれば質問者のコードで上手くいきそうですが
hana-hana3さんの回答にもあるようにThisWorkBook.Closeでコード終了となりますので
Application.QuitをThisWorkBook.Closeの前にもってこないといけません。
Application.Quitはそれがあるプロシージャのコードが全て終わるまで
その実行を保留するちょと特別動作をします。

'-------------------------------------
 Application.Quit
 ThisWorkbook.Close
'-------------------------------------
 
 

QVB上で実行中の無限ループの止め方

今まで、CUIベースのBASICでのプログラムの経験はあるのですが
Visual系のBASICは初心者です。
原因はわかっているのでプログラムの修正はできるのですが
VB上でコンパイルして実行したときに無限ループに陥ってしまって
どうにもプログラムをとめられなくなります。
そんなことがないように、実行前に全てのプロジェクトを保存して
いますので、そんなに実害はないのですが、どうすればとめられるのでしょう・・
今現在は、タスクマネージャーから強制終了させています。

Aベストアンサー

無限ループの一番内側に
DoEvents
を入れておくと、ウィンドウ切替え->デバッガ終了操作が出来ますよ

危なそうなとこにも入れておくと、何かと安心です。

Q別のシートから値を取得するとき

Worksheets("シート名").Activate
上記のを行ってから別シートの値を取得するのですが、
この処理を行うと指定したシートへ強制的にとんでしまいます。。。

※イメージ
For ~ To ~
  Worksheets("シートA").Activate
  シートAの値取得
       :
  Worksheets("シートB").Activate
  シートBの値取得
Next

このイメージ処理を行うとものすごい勢いで画面がチカチカします。。。
シートを変えずに他のシートから値を取得する方法はないのでしょうか。
教えてください!

Aベストアンサー

Worksheets("シートA").Range("A1")

みたいな感じでできませんか?

QDoEvents関数って何?

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そこで「EXCEL VBA パーフェクトマスター」という本を見たら

for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
DoEvents
next i
unload userform1
と入力すれば解決することがわかりました。

しかし「DoEvents」についてあまり詳しく書いていなかったのでDoEvents関数をヘルプで見ると、
「発生したイベントがオペレーティング システムによって処理されるように、プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数です。」

と書いてあるのですが正直、書いてあることがよくわかりません。

どなたかDoEvents関数について、
もう少しわかりやすく教えていただけませんか。
それから、最初に書いたコードで実行すると
ユーザーフォームの背景が真っ白になってしまう原因も
教えていただけませんか?

よろしくお願いいたします。

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そ...続きを読む

Aベストアンサー

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
    DoEvents
    Cells(i,1) = ""
  Next i
End Sub

Private Sub CommandButton2_Click()
  MsgBox "hoge"
End Sub

っていうフォームのコードがあった場合、
DoEvents を入れることによって、ループ中にユーザーがCommandButton2 を押すことによって CommandButton2 のクリック イベントも動いちゃいます。
CommandButton1 のクリック イベントではループの前に
CommandButton1.Enabled = False
CommandButton2.Enabled = False
を書いてフォーム上の CommandButton を無効にしておき、ループが終わったら
CommandButton1.Enabled = True
CommandButton2.Enabled = True
と書いて CommandButton を有効に戻してください。

これを工夫すれば、CommandButton2 で CommandButton1 のループを途中キャンセルする処理もすることができます。

Private Canceled As Boolean

Private Sub CommandButton1_Click()

  CommandButton2.Enabled = False

  Dim i As Long
  For i = 1 To 50000
    DoEvents

    If Canceled = True Then
      MsgBox "キャンセルしました"
      Exit Sub
    End If

    Cells(i, 1).Value = ""
  Next i
End Sub

Private CommandButton2_Click()
  Canceled = True
End Sub



コードの行頭にあるスペースは見易さのために全角スペースで作成していますので、これをこのままコピペするとエラーになるかもしれません。
コピペするなら行頭の全角スペースを半角スペースに直してください。

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング