いつもお世話になっております。

現在VB6.0にて、CSVファイルを読み込む処理をしています。
・ファイル読み込みにて1行ファイルを読み込む。
・Split関数で「,」で区切って項目ごとに配列に保持する。
というロジックで作成しているのですが、
項目内に改行コードが存在する場合にうまく読み込めません。
(1行ずつ読んでるので当然ですが…)

項目内のコードをLF、実際の行の改行をCR+LFで区別すると読み込む
のは分かるのですが、項目内の改行コードがCR+LFの場合でも、
正しく読み込みたいです。

以上です。よろしくお願い致します。

A 回答 (5件)

    • good
    • 1

意味的に、列に相当する、数字は一定ではないのですか


フィールド数 5(カンマ4つ)ーー第1レコード(Line Inputで読んで)
3(カンマ2つ)ーー第2レコード
2(カンマ1ツ)ーー第3レコード
・・
のようであればSplitしたUbound数を足して行き、5になったら
一般通常でのケースの、次行の扱いをするロジックで解決しませんか。
それで不可能なら、この質問のケースの、たまたまの好都合条件を捉えて、意味的に先頭フィールドを探すとかしかなくなる。
他フィールドにはない。例えば完成形のデータを考えると、先頭に7桁の定桁数字が来るとか。
コンピュタープログラム作成と言うのは、特賞を捉えて処理を進める
学だとお思います。
    • good
    • 0

#1 Wizard_Zeroです。



ダブルクォートでくくられているのであれば、
・ダブルクォートで終わる行はそのままSplit
・それ以外なら次の行も連結

でいけると思います。
ただ、データ内にカンマがあればこれまた厄介で、地道にダブルクォートを考慮しながら切り分ける必要があります。
(これも、行の前後のダブルクォート取り除いて "," で分解すればいいんですけどね。", " のように間にスペースがあったりするとまた厄介という・・・)
    • good
    • 0

根本的に設計ミスです。



項目内に改行を含む場合は、CSVはダブルクォーテーションでくくる形式にするようにするのが、定石です。

この回答への補足

ご回答ありがとうございます。
記述漏れでしたが、
CSVファイルは全ての項目がともダブルクォーテーションでくくられています。
説明不足で申し訳ありません。

補足日時:2009/05/20 11:00
    • good
    • 0

CSVファイルの1レコードあたりの項目数が固定という前提で、Splitで分解したときに項目数が足りない時は次の行と連結してSplitする。



という方法を思いついたのですが、レコードの最後の項目が改行されていたらうまくいきませんね・・・。
この場合、次の行には前の行における最後の項目の残りだけが記録されるので、カンマのない行は前の列と連結としたいところですが、そうなると今度は、最初の項目で改行されていたら・・・というジレンマに陥ります。
(最初と最後の項目が絶対に改行されないのであればこのあたりを考慮する必要はありませんが…)

どちらにしても、レコードに改行が含まれていることを明確に知る手段が必要になるでしょう。
・レコード内の改行コードはLFに限定する
・改行コードのあるレコードはダブルクォーテーションでくくる
などのルールがあれば、それにあわせて読み込みも出来るようになります。

もしこのようなことが出来ないのであれば、100%の精度で読み込むことはできないため、読み込んだあとにレコードを手動で変更できる手段を提供する必要があると思います。

この回答への補足

ご回答ありがとうございます。
記述漏れでしたが、
・改行コードのあるレコードはダブルクォーテーションでくくる
は既に実現されています。
説明不足で申し訳ありません。

補足日時:2009/05/20 10:59
    • good
    • 0

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

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

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

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

QEXCELにcsv形式の外部データを取り込む際にカンマ区切りで取り込も

EXCELにcsv形式の外部データを取り込む際にカンマ区切りで取り込もうとした場合、csvデータの同一セル内に改行データがあると、ずれて表示されてしまいます。
改行を取り除くのはclean関数があることは知っていますが、マクロを利用して、EXCELのデータ→外部データの取り込みの選択だけで取り込む方法はないでしょうか?ご教示ください。

Aベストアンサー

Sub try()
  Dim WRK As String '一時作業ファイル名。削除するので既存ファイル名と重複させないように。
  Dim buf As String
  Dim tmp As String
  Dim n  As Long
  Dim f

  '読込みファイルを選択
  f = Application.GetOpenFilename("csv,*.csv")
  If VarType(f) = vbBoolean Then Exit Sub
  '作業ファイル名設定
  WRK = Application.DefaultFilePath & "\temporary.csv"
  '読込みファイルOpen
  n = FreeFile
  Open f For Input As #n
  buf = StrConv(InputB(LOF(n), #n), vbUnicode)
  Close #n
  '置換(セル内改行を半角スペースに)
  With CreateObject("VBScript.RegExp")
    .Global = True
    .Pattern = "([^\r])(\n+)"
    buf = .Replace(buf, "$1 ")
  End With
  '作業ファイルOpen
  n = FreeFile
  Open WRK For Output As #n
  Print #n, buf
  Close #n
  '[外部データの取り込み]
  With Sheets.Add
    With .QueryTables.Add(Connection:="TEXT;" & WRK, _
               Destination:=.Range("A1"))
      .AdjustColumnWidth = False
      .TextFileParseType = xlDelimited
      .TextFileTextQualifier = xlTextQualifierDoubleQuote
      .TextFileCommaDelimiter = True
      .Refresh BackgroundQuery:=False
      .Delete
    End With
  End With
  '作業ファイル削除
  Kill WRK
End Sub

Excelで作成したcsvファイルで、セル内改行が含まれている場合は上記で読み込めるはずです。
そのcsvファイルをテキストエディタで編集してしまった場合は、うまくいかなくなるかもしれません。

'[外部データの取り込み]...以降、 Kill WRK までのコードは、無くても構いません。
取り込み前にセル内改行を置換してしまえば、
あとは手作業ででも[外部データの取り込み]ができます。

Sub try()
  Dim WRK As String '一時作業ファイル名。削除するので既存ファイル名と重複させないように。
  Dim buf As String
  Dim tmp As String
  Dim n  As Long
  Dim f

  '読込みファイルを選択
  f = Application.GetOpenFilename("csv,*.csv")
  If VarType(f) = vbBoolean Then Exit Sub
  '作業ファイル名設定
  WRK = Application.DefaultFilePath & "\temporary.csv"
  '読込みファイルOpen
  n = FreeFile
  Open f For Input As #n
  buf = StrConv(InputB(LOF(n),...続きを読む

Q文字列にある特定文字の数

こんにちは。

文字列「C:\MYDOCU~1\THINKB~1\THINKB~1\TEMP」に"¥"がいくつ含まれているかを算出したく悩んでいます。どのような方法があるのか、是非アドバイスをください。よろしくお願いします。

** 環境 **
VB6.0(sp5)

Aベストアンサー

ご質問の「文字列」から察するにあるファイルのパス(ドライブ+パス+ファイル名)を
ドライブ+パスとファイル名に分解する、のような使い方をされるのでしょうか?
先の例ですとstrArrey(numArrey)を参照すると「ファイル名のみ」が取得できます。

あと、Splitの反対で「JOIN関数」があります。
なお、Split,JoinはExcel2000以降のVBAでも利用可能です。


'ここから

Dim strArrey() As String
Dim numArrey As Integer

Dim strPath As String

strPath = "C:\MYDOCU~1\THINKB~1\THINKB~1\TEMP"

strArrey() = Split(strPath, "\")

numArrey = UBound(strArrey())

MsgBox "これがファイル名:[" & strArrey(numArrey) & "]"

strArrey(numArrey) = ""

strPath = Join(strArrey(), "\")

MsgBox "これがパス名:[" & strPath & "]"

'ここまで

ご質問の「文字列」から察するにあるファイルのパス(ドライブ+パス+ファイル名)を
ドライブ+パスとファイル名に分解する、のような使い方をされるのでしょうか?
先の例ですとstrArrey(numArrey)を参照すると「ファイル名のみ」が取得できます。

あと、Splitの反対で「JOIN関数」があります。
なお、Split,JoinはExcel2000以降のVBAでも利用可能です。


'ここから

Dim strArrey() As String
Dim numArrey As Integer

Dim strPath As String

strPath = "C:\MYDOCU~1\THINKB~1\THINKB~1...続きを読む

Qテキストファイルから改行コードを削除して読込む方法

ExcelエクセルVBAマクロについてテキストファイルから改行コードを取り除いて
変数に読み込む方法について確認させてください。

下記のVBAログラムはWordファイルをテキストファイルに落としたファイルを変数aに
読み込んでいます。
このとき、読み込んだテキストファイルはWordファイルをテキストファイルに
落とし込んだファイルなので改行コードが残ってしまいます。
この改行コードを削除したうえで変数aに読み込みたいのですが可能でしょうか。
改行コードはメモ帳では「↓」と下矢印に似た文字で表示されます。
(実際には下矢印ではないようです。)
今のところ、Replace関数で改行コードを削除するプログラムを
考えているのですが、改行コードのVBAでの表現方法が分からないので
先に進むことが出来ません。いい案があればぜひご教授下さい。
あるいはほかの方法でも改行コードが削除出来れば結構です。

またこの変数aに読み込んである文字列からかぎカッコの内部にある文字を
抽出してエクセルの行方向に出力する方法があればご教授頂ければ幸いです。
例えば
“あなたは「こんにちは」と言いました。
私は「元気ですか」と聞きました。”

が文字列aに読み込んである場合、“こんにちは”、“元気ですか”を抽出して
エクセルに順に出力という方法です。

色々と書きましたが、よろしくお願いいたします。
以下、VBAプログラム本文です。

----------------------------------
Sub sample1()

Dim a As String

a = CreateObject("Scripting.FileSystemObject").GetFile("C:\sample.txt").OpenAsTextStream.Readall
CreateObject("Scripting.FileSystemObject").GetFile("C:\sample.txt").OpenAsTextStream.Close

End Sub

ExcelエクセルVBAマクロについてテキストファイルから改行コードを取り除いて
変数に読み込む方法について確認させてください。

下記のVBAログラムはWordファイルをテキストファイルに落としたファイルを変数aに
読み込んでいます。
このとき、読み込んだテキストファイルはWordファイルをテキストファイルに
落とし込んだファイルなので改行コードが残ってしまいます。
この改行コードを削除したうえで変数aに読み込みたいのですが可能でしょうか。
改行コードはメモ帳では「↓」と下矢印に似た文字で表示されま...続きを読む

Aベストアンサー

Windowsの改行はCRLFです。#1さんの仰るとおり、chr(13)+chr(10)ですね。
あるいはvbCr,vbLf,vbCrLfなんてのもあります。

あとプログラム本文は良くないです。
最低でもこう書くべきです。
'-------------------------------------------------
dim objStream as Object
set objStream = CreateObject("Scripting.FileSystemObject").GetFile("C:\sample.txt").OpenAsTextStream
a=objStream.readall
objStream.Close
'--------------------------------------------------
もとのソースだと、...OpenAsTextStreamと書いた時点でテキストを開いてます。
1回目と2回目は別のモノ。つまり2回開いてて、1回目は開きっぱなし。

>かぎカッコの内部にある文字を抽出

これはご自分で考えてみて下さい。
例えば、crlfを除去したのなら
b=replace(a,"「",vbcr)
b=replace(b,"」",vbcr)
とでもしておいてvbcrでSplit()すれば配列の奇数番目が括弧の中身です。
括弧が閉じてない場合とか半角だったりする場合とかもあるので注意ですね。
一番良いのは正規表現を使う方法ですが、これはちょっとハードルが高いでしょう。

Windowsの改行はCRLFです。#1さんの仰るとおり、chr(13)+chr(10)ですね。
あるいはvbCr,vbLf,vbCrLfなんてのもあります。

あとプログラム本文は良くないです。
最低でもこう書くべきです。
'-------------------------------------------------
dim objStream as Object
set objStream = CreateObject("Scripting.FileSystemObject").GetFile("C:\sample.txt").OpenAsTextStream
a=objStream.readall
objStream.Close
'--------------------------------------------------
もとのソースだと、...OpenAsTextSt...続きを読む

Qデータにカンマが入ったCSVデータのread方法

VBにてCSVデータを読み込むロジックを組んでいるのですが
データの中にカンマが入ったものがたまにあります。
通常通り読むとデータのカンマを区切りのカンマと間違え正しく変数に読み込まれません。
たとえばCSVデータが下記の場合
123,de-ta,12,000,jjjj
実際のデータは
123
de-ta
12,000
jjjj
ですが
12,000を2個のデータと認識して
123
de-ta
12
0000
jjjj
のようになってしまいます。
どなたか12,000をちゃんと読める方法をご存知の方お力をお貸しください。
よろしくお願い致します。

Aベストアンサー

こんにちは
そのアプリは、固定長出力はできないでしょうか。
二重引用符もだめだとすると、規則性を利用してロジックで分けるしかありません。
例えば・・
Line Input で1行ずつ取り込み。
念のためカンマの数をカウントしてみる。
カンマの位置で、データを切り出す。Instr()かVB6のSplit()で。
IsNumeric(str)を利用して、データが数値か文字列かを判断する。
例ですと、数値の後ろの項目は文字列になっているので、文字列が後ろに来たら、そこまでの数値を連結する。
てな具合です。
では!

Qダブルクォーテーションを文字列として扱いたい

 初心者な質問で申し訳ありませんが、ダブルクォーテーション("")を
 文字列として扱いたいのですが、どうもうまくいきません。
 SQLなどだと、escapeって関数がありますよね?
 VBにはそれに似たような関数はあるのでしょうか??

Aベストアンサー

msgbox "ダブルクォーテーションは""と書けばよい"

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
...続きを読む

QVBでグローバル変数を宣言するには

VB初心者ですが。クイズゲームのようなものを作成したいと考えてます。
Private Sub ~ End Sub の中で宣言した変数って他のところに呼び出したり(戻り値として渡す)出来るのでしょうか?
どこでも、いつでも呼び足せるグローバル変数の宣言とはどのようにやるのか、具体的に教えていただけないでしょうか?

Aベストアンサー

>Public a as Integerのように宣言して、初期化するにはどのように記述を行えばよいですか?

>Public a As Boolean = 0
のように記したら”コンパイルエラー”と出ました。

Booleanって整数値取れたかなと思いつつ。
Sub~End Sub内でa = 0を代入したりしてください

扱おうと言うことがあるかどうか疑問だけど

Public Const a As Integer = 10 'グローバルな定数の宣言

QVBA オブジェクトが空かどうか判定する

皆様のお知恵を拝借させてください。

エクセルVBAでオブジェクトを入れる変数を定義し、その変数にオブジェクト
が入っているかどうか検査したいのですがどうしたらいいでしょうか。

例えば---
Dim a As Workbook
If a <> nothing then ←この部分が分からない。このままだとエラー。
処理
End if
---------
環境
エクセル2003
WinXPsp1

Aベストアンサー

もし、aが空だったら
If a Is Nothing Then 

もし、aが空じゃなかったら
If Not a Is Nothing Then

Q日付型のフィールドに空白を入れる方法を教えてください

ASP(VBScript)でSQLサーバにINSET INTO文を使ってデータを格納しているのですが、日付の部分がNULLの時、「1900/1/1」が入ってしまいます。
そのまま、空白を入れる方法はどうやったらよろしいのでしょうか?

TABLE1の内容は
番号|内容|日付です。

INSERT INTO TABLE1 VALUES ( 1, 'あいう', '')

結果
1|あいう|1900/1/1

Aベストアンサー

あとは、プログラムの書き方次第ですね、、、


If hensu=Null Or hensu="" Then
dt = "NULL"
Else
dt = "'" & hensu & "'"
End IF

E_SQL = "INSERT INTO TABLE1 VALUES & _
"( 1,'あいう', " & dt& ")"
の様に書きます。

Q他言語で言うcontinue文

他言語で言うcontinue文に相当する命令はVBに用意されているのでしょうか?

continue文とはループ中の後続の処理をやめループの先頭に戻るという命令です。

なんか探したけど無かったもので…。どんな言語にも用意されてそうな基本的な命令なので質問してみました。

バージョンは
Winエクセル2002 SP3
VBA Retail:6.4.8869, Version:9969
です。基本エンジンはVB6です。

よろしくお願いします。

Aベストアンサー

> continue文の解説でも、貴方のご指摘の動作(ループの先頭に戻る)はしているようには思えません。

ループの最後へジャンプという感じですね。
VBなら、Nextへ飛ばすのと同じです。

For i = 1 To 5
    If i = 3 Then goto Next_i
    Debug.Print i
Next_i:
Next i


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

人気Q&Aランキング

おすすめ情報