Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


6305 / 13646 ツリー ←次へ | 前へ→

【46027】36128について教えて下さい おおい 07/1/21(日) 15:31 質問[未読]
【46033】Re:36128について教えて下さい Kein 07/1/21(日) 17:58 回答[未読]
【46034】Re:36128について教えて下さい neptune 07/1/21(日) 18:14 回答[未読]
【46035】Re:36128について教えて下さい Hirofumi 07/1/21(日) 18:16 回答[未読]
【46036】Re:36128について教えて下さい おおい 07/1/21(日) 18:25 発言[未読]
【46038】Re:36128について教えて下さい Hirofumi 07/1/21(日) 19:09 回答[未読]
【46041】Re:36128について教えて下さい おおいくん 07/1/21(日) 20:33 お礼[未読]

【46027】36128について教えて下さい
質問  おおい  - 07/1/21(日) 15:31 -

引用なし
パスワード
   型が一致しませんと出てしまうのですが
原因わかりません
よろしくお願いします。

以下36128のコピーです
db.csvは本マクロを含むブックと同一フォルダにあるものとします。
これでできます。

'''''''''''''''''以下は標準モジュールに貼り付けて下さい
Sub test()
Dim w As Workbook
Dim flag As Boolean
  Sheets("Sheet1").Cells.Clear
  Read_CSV
  UserForm1.Show
End Sub

Sub Read_CSV()
  Dim dat As Variant
  Dim rw As Long
  Dim vntA() As Variant
  '
  Open ThisWorkbook.Path & "\db.csv" For Input As #1
  rw = 1
  Do Until EOF(1)
    Line Input #1, dat
    ReDim Preserve vntA(1 To rw)
    vntA(rw) = Split(dat, ",")
    rw = rw + 1
  Loop
  Close #1
  Sheets("Sheet1").Range("A1").Resize(UBound(vntA), UBound(vntA(1)) + 1).Value _  ★ココでエラー発生★
        = Application.Transpose(Application.Transpose(vntA))
  Erase vntA
End Sub

'''''''''''''''''以下はUserForm1モジュールに貼り付けて下さい
UserForm1にはTextBox1とListBox1とCommandButton1を作ります


Private Sub CommandButton1_Click()
Dim r As Range, FirstCell As Range, rng As Range
Dim vnt As Variant
Dim prow As Long
Dim s As Worksheet
Dim cnt As Long
  '
  Set s = Sheets("Sheet1")
  Set rng = Intersect(s.Range("A:G"), s.UsedRange)
  Set r = rng.Find(What:=TextBox1.Text)
  If r Is Nothing Then GoTo Exit_sub
  Set FirstCell = r
  ReDim vnt(0)
  vnt(0) = s.Cells(r.Row, 1).Resize(1, 7).Value
  prow = r.Row  '同じ行かチック
  cnt = 1
  Do
    Set r = s.UsedRange.FindNext(r)
    If Not r Is Nothing And (r.Address <> FirstCell.Address) _
        And (FirstCell.Row <> r.Row) And (prow <> r.Row) Then
      ReDim Preserve vnt(UBound(vnt) + 1)
      vnt(UBound(vnt)) = s.Cells(r.Row, 1).Resize(1, 7).Value
      prow = r.Row
      cnt = cnt + 1
    End If
  Loop While r.Address <> FirstCell.Address
  '
  If cnt = 1 Then vnt = s.Cells(FirstCell.Row, 1).Resize(1, 7).Value
  If cnt > 1 Then vnt = Application.Transpose(Application.Transpose(vnt))
  ListBox1.List = vnt
  '
  Set FirstCell = Nothing
  Erase vnt
Exit_sub:
  If cnt = 0 Then ListBox1.Clear
  Set r = Nothing
  Set rng = Nothing
  Set s = Nothing
End Sub

Private Sub UserForm_Initialize()
  ListBox1.ColumnCount = 7  'ListBox1の列は7列にする
  Me.TextBox1.SetFocus
End Sub

【46033】Re:36128について教えて下さい
回答  Kein  - 07/1/21(日) 17:58 -

引用なし
パスワード
   1行読み込んで配列に入れ、それをシートに入力・・を繰り返す方法でよい
と思いますよ。

Sub test()
  With Sheets("Sheet1")
    .Cells.Clear
    .Activate
  End With
  Read_CSV
  UserForm1.Show
End Sub

Sub Read_CSV()
  Dim Buf As String
  Dim dat As Variant
  Dim rw As Long
  
  Open ThisWorkbook.Path & "\db.csv" For Input As #1
  Do Until EOF(1)
    Line Input #1, Buf
    dat = Split(Buf, ","): rw = rw + 1
    Cells(rw, 1).Resize(, UBound(dat) + 1).Value = dat
    Erase dat: Buf = ""
  Loop
  Close #1
End Sub

【46034】Re:36128について教えて下さい
回答  neptune  - 07/1/21(日) 18:14 -

引用なし
パスワード
   こんにちは

実データがなく検証もしてないので、外しかも知れませんが、
気になる点を書いておきます。

>  Sheets("Sheet1").Range("A1").Resize(UBound(vntA), UBound(vntA(1)) + 1).Value _  ★ココでエラー発生★
Uboundは要素がないとエラーになります。

mRow=UBound(vntA)
mCol=UBound(vntA(1))

Sheets("Sheet1").Range("A1").Resize(mRow, mCol + 1).Value = _
= Application.Transpose(Application.Transpose(vntA))

として切り分けて考えてみてはどうですか?
ステップ数が少なければ良いということはありません。

UBoundは要素がなければ確実にエラーになりますから
そこは、確実にエラー対策をしなければなりません。

【46035】Re:36128について教えて下さい
回答  Hirofumi  - 07/1/21(日) 18:16 -

引用なし
パスワード
   多分こんなで、同じ様な事をやると思いますが?
ただし、CsvはSheetに展開をしません、直接ListBoxに代入されます
尚、TextBox1に設定される値には、Like演算のでワイルドカード(?、*)が使用出来ます

以下をUserFormのコードモジュールに全て記述して下さい

Option Explicit

'探索を行う、ListBoxに表示する列数(CSV先頭から7列)
Private Const clngColumns As Long = 7

'読み込むTextFile名
Private vntFileName As Variant

Private Sub CommandButton1_Click()

  Dim i As Long
  Dim j As Long
  Dim dfn As Integer
  Dim strBuff As String
  Dim strRec As String
  Dim blnMulti As Boolean
  Dim vntField As Variant
  Dim vntKey As Variant
  
  'TextBox1に値が設定されて居なければ
  If TextBox1.Text = "" Then
    Beep
    Exit Sub
  Else
    'TextBox1の値をKey文字とする
    vntKey = Trim(TextBox1.Text)
  End If
  
  'ListBoxをクリア
  ListBox1.Clear
  
  'CsvファイルをOpen
  dfn = FreeFile
  Open vntFileName For Input As dfn

  Do Until EOF(dfn)
    '1行読み込み
    Line Input #dfn, strBuff
    '論理レコードに物理レコードを追加
    strRec = strRec & strBuff
    '論理レコードをフィールドに分割
    vntField = SplitCsv(strRec, ",", , , blnMulti)
    'フィールド内で改行が無い場合
    If Not blnMulti Then
      'Csv先頭から7列の中にKey文字が含まれるか検査
      For i = 0 To clngColumns - 1
        '含まれている場合
        If vntField(i) Like vntKey Then
          Exit For
        End If
      Next i
      'レコードにKey文字が有った場合
      If i <= clngColumns - 1 Then
        'ListBox1に項目を追加
        With ListBox1
          .AddItem vntField(0)
          For j = 1 To clngColumns - 1
            .List(.ListCount - 1, j) = vntField(j)
          Next j
        End With
      End If
      strRec = ""
    End If
  Loop

  Close #dfn

End Sub

Private Sub UserForm_Initialize()

  ListBox1.ColumnCount = 7
  
End Sub

Private Sub UserForm_Activate()

  '読み込むファイル名を設定
  vntFileName = "db"
  'ファイルを開くダイアログを表示
  If Not GetReadFile(vntFileName, ThisWorkbook.Path, False) Then
    Unload Me
    MsgBox "マクロがキャンセルされました", vbInformation
  End If
  
End Sub

Private Function SplitCsv(ByVal strLine As String, _
            Optional strDelimiter As String = ",", _
            Optional strQuote As String = """", _
            Optional strRet As String = vbCrLf, _
            Optional blnMulti As Boolean) As Variant

'      strLine     :分割元と成る文字列
'      strDelimiter  :区切り文字
'      SplitCsv    :戻り値、切り出された文字配列

  Dim lngDPos As Long
  Dim vntData() As Variant
  Dim lngStart As Long
  Dim i As Long
  Dim vntField As Variant
  Dim lngLength As Long
  
  i = 0
  lngStart = 1
  lngLength = Len(strLine)
  blnMulti = False
  Do
    ReDim Preserve vntData(i)
    If Mid$(strLine, lngStart, 1) <> strQuote Then
      lngDPos = InStr(lngStart, strLine, _
            strDelimiter, vbBinaryCompare)
      If lngDPos > 0 Then
        vntField = Mid$(strLine, lngStart, _
                  lngDPos - lngStart)
        If lngDPos = lngLength Then
          ReDim Preserve vntData(i + 1)
        End If
        lngStart = lngDPos + 1
      Else
        vntField = Mid$(strLine, lngStart)
        lngStart = lngLength + 1
      End If
    Else
      lngStart = lngStart + 1
      Do
        lngDPos = InStr(lngStart, strLine, _
                strQuote, vbBinaryCompare)
        If lngDPos > 0 Then
          vntField = vntField & Mid$(strLine, _
                lngStart, lngDPos - lngStart)
          lngStart = lngDPos + 1
          Select Case Mid$(strLine, lngStart, 1)
            Case ""
              Exit Do
            Case strDelimiter
              lngStart = lngStart + 1
              Exit Do
            Case strQuote
              lngStart = lngStart + 1
              vntField = vntField & strQuote
          End Select
        Else
          blnMulti = True
          vntField = Mid$(strLine, lngStart) & strRet
          lngStart = lngLength + 1
          Exit Do
        End If
      Loop
    End If
    vntData(i) = vntField
    vntField = Empty
    i = i + 1
  Loop Until lngLength < lngStart
  
  SplitCsv = vntData()
  
End Function

Private Function GetReadFile(vntFileNames As Variant, _
            Optional strFilePath As String, _
            Optional blnMultiSel As Boolean _
                    = False) As Boolean

  Dim strFilter As String
  
  'フィルタ文字列を作成
  strFilter = "CSV File (*.csv),*.csv," _
        & "Text File (*.txt),*.txt," _
        & "CSV and Text (*.csv; *.txt),*.csv;*.txt," _
        & "全て (*.*),*.*"
  '読み込むファイルの有るフォルダを指定
  If strFilePath <> "" Then
    'ファイルを開くダイアログ表示ホルダに移動
    ChDrive Left(strFilePath, 1)
    ChDir strFilePath
  End If
  'もし、ディフォルトのファイル名が有る場合
  If vntFileNames <> "" Then
    SendKeys vntFileNames & "{TAB}", False
  End If
  '「ファイルを開く」ダイアログを表示
  vntFileNames _
      = Application.GetOpenFilename(strFilter, 1, , , blnMultiSel)
  If VarType(vntFileNames) = vbBoolean Then
    Exit Function
  End If
  
  GetReadFile = True
  
End Function

【46036】Re:36128について教えて下さい
発言  おおい  - 07/1/21(日) 18:25 -

引用なし
パスワード
   keinさん
▼Hirofumi さん:
ありがとうございます。
Keinさんのでうまく動きました
Hirohumiさんの
If vntField(i) Like vntKey Thenこの部分で
インデックスが範囲を超えていますと出てしまいました。
いかがでしょうか


>多分こんなで、同じ様な事をやると思いますが?
>ただし、CsvはSheetに展開をしません、直接ListBoxに代入されます
>尚、TextBox1に設定される値には、Like演算のでワイルドカード(?、*)が使用出来ます
>
>以下をUserFormのコードモジュールに全て記述して下さい
>
>Option Explicit
>
>'探索を行う、ListBoxに表示する列数(CSV先頭から7列)
>Private Const clngColumns As Long = 7
>
>'読み込むTextFile名
>Private vntFileName As Variant
>
>Private Sub CommandButton1_Click()
>
>  Dim i As Long
>  Dim j As Long
>  Dim dfn As Integer
>  Dim strBuff As String
>  Dim strRec As String
>  Dim blnMulti As Boolean
>  Dim vntField As Variant
>  Dim vntKey As Variant
>  
>  'TextBox1に値が設定されて居なければ
>  If TextBox1.Text = "" Then
>    Beep
>    Exit Sub
>  Else
>    'TextBox1の値をKey文字とする
>    vntKey = Trim(TextBox1.Text)
>  End If
>  
>  'ListBoxをクリア
>  ListBox1.Clear
>  
>  'CsvファイルをOpen
>  dfn = FreeFile
>  Open vntFileName For Input As dfn
>
>  Do Until EOF(dfn)
>    '1行読み込み
>    Line Input #dfn, strBuff
>    '論理レコードに物理レコードを追加
>    strRec = strRec & strBuff
>    '論理レコードをフィールドに分割
>    vntField = SplitCsv(strRec, ",", , , blnMulti)
>    'フィールド内で改行が無い場合
>    If Not blnMulti Then
>      'Csv先頭から7列の中にKey文字が含まれるか検査
>      For i = 0 To clngColumns - 1
>        '含まれている場合
>        If vntField(i) Like vntKey Then
>          Exit For
>        End If
>      Next i
>      'レコードにKey文字が有った場合
>      If i <= clngColumns - 1 Then
>        'ListBox1に項目を追加
>        With ListBox1
>          .AddItem vntField(0)
>          For j = 1 To clngColumns - 1
>            .List(.ListCount - 1, j) = vntField(j)
>          Next j
>        End With
>      End If
>      strRec = ""
>    End If
>  Loop
>
>  Close #dfn
>
>End Sub
>
>Private Sub UserForm_Initialize()
>
>  ListBox1.ColumnCount = 7
>  
>End Sub
>
>Private Sub UserForm_Activate()
>
>  '読み込むファイル名を設定
>  vntFileName = "db"
>  'ファイルを開くダイアログを表示
>  If Not GetReadFile(vntFileName, ThisWorkbook.Path, False) Then
>    Unload Me
>    MsgBox "マクロがキャンセルされました", vbInformation
>  End If
>  
>End Sub
>
>Private Function SplitCsv(ByVal strLine As String, _
>            Optional strDelimiter As String = ",", _
>            Optional strQuote As String = """", _
>            Optional strRet As String = vbCrLf, _
>            Optional blnMulti As Boolean) As Variant
>
>'      strLine     :分割元と成る文字列
>'      strDelimiter  :区切り文字
>'      SplitCsv    :戻り値、切り出された文字配列
>
>  Dim lngDPos As Long
>  Dim vntData() As Variant
>  Dim lngStart As Long
>  Dim i As Long
>  Dim vntField As Variant
>  Dim lngLength As Long
>  
>  i = 0
>  lngStart = 1
>  lngLength = Len(strLine)
>  blnMulti = False
>  Do
>    ReDim Preserve vntData(i)
>    If Mid$(strLine, lngStart, 1) <> strQuote Then
>      lngDPos = InStr(lngStart, strLine, _
>            strDelimiter, vbBinaryCompare)
>      If lngDPos > 0 Then
>        vntField = Mid$(strLine, lngStart, _
>                  lngDPos - lngStart)
>        If lngDPos = lngLength Then
>          ReDim Preserve vntData(i + 1)
>        End If
>        lngStart = lngDPos + 1
>      Else
>        vntField = Mid$(strLine, lngStart)
>        lngStart = lngLength + 1
>      End If
>    Else
>      lngStart = lngStart + 1
>      Do
>        lngDPos = InStr(lngStart, strLine, _
>                strQuote, vbBinaryCompare)
>        If lngDPos > 0 Then
>          vntField = vntField & Mid$(strLine, _
>                lngStart, lngDPos - lngStart)
>          lngStart = lngDPos + 1
>          Select Case Mid$(strLine, lngStart, 1)
>            Case ""
>              Exit Do
>            Case strDelimiter
>              lngStart = lngStart + 1
>              Exit Do
>            Case strQuote
>              lngStart = lngStart + 1
>              vntField = vntField & strQuote
>          End Select
>        Else
>          blnMulti = True
>          vntField = Mid$(strLine, lngStart) & strRet
>          lngStart = lngLength + 1
>          Exit Do
>        End If
>      Loop
>    End If
>    vntData(i) = vntField
>    vntField = Empty
>    i = i + 1
>  Loop Until lngLength < lngStart
>  
>  SplitCsv = vntData()
>  
>End Function
>
>Private Function GetReadFile(vntFileNames As Variant, _
>            Optional strFilePath As String, _
>            Optional blnMultiSel As Boolean _
>                    = False) As Boolean
>
>  Dim strFilter As String
>  
>  'フィルタ文字列を作成
>  strFilter = "CSV File (*.csv),*.csv," _
>        & "Text File (*.txt),*.txt," _
>        & "CSV and Text (*.csv; *.txt),*.csv;*.txt," _
>        & "全て (*.*),*.*"
>  '読み込むファイルの有るフォルダを指定
>  If strFilePath <> "" Then
>    'ファイルを開くダイアログ表示ホルダに移動
>    ChDrive Left(strFilePath, 1)
>    ChDir strFilePath
>  End If
>  'もし、ディフォルトのファイル名が有る場合
>  If vntFileNames <> "" Then
>    SendKeys vntFileNames & "{TAB}", False
>  End If
>  '「ファイルを開く」ダイアログを表示
>  vntFileNames _
>      = Application.GetOpenFilename(strFilter, 1, , , blnMultiSel)
>  If VarType(vntFileNames) = vbBoolean Then
>    Exit Function
>  End If
>  
>  GetReadFile = True
>  
>End Function

【46038】Re:36128について教えて下さい
回答  Hirofumi  - 07/1/21(日) 19:09 -

引用なし
パスワード
   >Hirohumiさんの
>If vntField(i) Like vntKey Thenこの部分で
>インデックスが範囲を超えていますと出てしまいました。
>いかがでしょうか

多分こう言うエラー出るなら、読み込むCsvに

'探索を行う、ListBoxに表示する列数(CSV先頭から7列)
Private Const clngColumns As Long = 7

で指定しているだけの列が無いのだと思います
例えば、上記でCsv先頭から7列を探索事に成ってますが?
実際のCsvが6列なら、当然エラーに成ります

以下を修正して下さい

Private Sub CommandButton1_Click()

  Dim i As Long
  Dim j As Long
  Dim dfn As Integer
  Dim strBuff As String
  Dim strRec As String
  Dim blnMulti As Boolean
  Dim vntField As Variant
  Dim vntKey As Variant
  Dim lngCount As Long '★追加
  
  'TextBox1に値が設定されて居なければ
  If TextBox1.Text = "" Then
    Beep
    Exit Sub
  Else
    'TextBox1の値をKey文字とする
    vntKey = Trim(TextBox1.Text)
  End If
  
  'ListBoxをクリア
  ListBox1.Clear
  
  'CsvファイルをOpen
  dfn = FreeFile
  Open vntFileName For Input As dfn

  Do Until EOF(dfn)
    '1行読み込み
    Line Input #dfn, strBuff
    '論理レコードに物理レコードを追加
    strRec = strRec & strBuff
    '論理レコードをフィールドに分割
    vntField = SplitCsv(strRec, ",", , , blnMulti)
    'フィールド内で改行が無い場合
    If Not blnMulti Then
      '実データ列数が予定データ数より小さい場合の処理
      lngCount = UBound(vntField) '★追加
      If lngCount > clngColumns - 1 Then '★追加
        lngCount = clngColumns - 1 '★追加
      End If '★追加
      'Csv先頭から7列の中にKey文字が含まれるか検査
'      For i = 0 To clngColumns - 1
      For i = 0 To lngCount '★変更
        '含まれている場合
        If vntField(i) Like vntKey Then
          Exit For
        End If
      Next i
      'レコードにKey文字が有った場合
'      If i <= clngColumns - 1 Then
      If i <= lngCount Then '★変更
        'ListBox1に項目を追加
        With ListBox1
          .AddItem vntField(0)
'          For j = 1 To clngColumns - 1
          For j = 1 To lngCount '★変更
            .List(.ListCount - 1, j) = vntField(j)
          Next j
        End With
      End If
      strRec = ""
    End If
  Loop

  Close #dfn

End Sub

【46041】Re:36128について教えて下さい
お礼  おおいくん  - 07/1/21(日) 20:33 -

引用なし
パスワード
   ▼Hirofumi さん:
エラー出ずにうまくいきましたありがとうございました。
またの機会もよろしくお願いします。(^_^)

>>If vntField(i) Like vntKey Thenこの部分で
>>インデックスが範囲を超えていますと出てしまいました。
>>いかがでしょうか
>
>多分こう言うエラー出るなら、読み込むCsvに
>
>'探索を行う、ListBoxに表示する列数(CSV先頭から7列)
>Private Const clngColumns As Long = 7
>
>で指定しているだけの列が無いのだと思います
>例えば、上記でCsv先頭から7列を探索事に成ってますが?
>実際のCsvが6列なら、当然エラーに成ります
>
>以下を修正して下さい
>
>Private Sub CommandButton1_Click()
>
>  Dim i As Long
>  Dim j As Long
>  Dim dfn As Integer
>  Dim strBuff As String
>  Dim strRec As String
>  Dim blnMulti As Boolean
>  Dim vntField As Variant
>  Dim vntKey As Variant
>  Dim lngCount As Long '★追加
>  
>  'TextBox1に値が設定されて居なければ
>  If TextBox1.Text = "" Then
>    Beep
>    Exit Sub
>  Else
>    'TextBox1の値をKey文字とする
>    vntKey = Trim(TextBox1.Text)
>  End If
>  
>  'ListBoxをクリア
>  ListBox1.Clear
>  
>  'CsvファイルをOpen
>  dfn = FreeFile
>  Open vntFileName For Input As dfn
>
>  Do Until EOF(dfn)
>    '1行読み込み
>    Line Input #dfn, strBuff
>    '論理レコードに物理レコードを追加
>    strRec = strRec & strBuff
>    '論理レコードをフィールドに分割
>    vntField = SplitCsv(strRec, ",", , , blnMulti)
>    'フィールド内で改行が無い場合
>    If Not blnMulti Then
>      '実データ列数が予定データ数より小さい場合の処理
>      lngCount = UBound(vntField) '★追加
>      If lngCount > clngColumns - 1 Then '★追加
>        lngCount = clngColumns - 1 '★追加
>      End If '★追加
>      'Csv先頭から7列の中にKey文字が含まれるか検査
>'      For i = 0 To clngColumns - 1
>      For i = 0 To lngCount '★変更
>        '含まれている場合
>        If vntField(i) Like vntKey Then
>          Exit For
>        End If
>      Next i
>      'レコードにKey文字が有った場合
>'      If i <= clngColumns - 1 Then
>      If i <= lngCount Then '★変更
>        'ListBox1に項目を追加
>        With ListBox1
>          .AddItem vntField(0)
>'          For j = 1 To clngColumns - 1
>          For j = 1 To lngCount '★変更
>            .List(.ListCount - 1, j) = vntField(j)
>          Next j
>        End With
>      End If
>      strRec = ""
>    End If
>  Loop
>
>  Close #dfn
>
>End Sub

6305 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free