Excel VBA質問箱 IV

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

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


4338 / 13644 ツリー ←次へ | 前へ→

【57168】CSVデータをACCESSに移行2. satsuki 08/7/30(水) 16:13 質問[未読]
【57183】Re:CSVデータをACCESSに移行2. neptune 08/7/30(水) 22:31 発言[未読]
【57188】Re:CSVデータをACCESSに移行2. satsuki 08/7/31(木) 0:47 質問[未読]
【57189】Re:CSVデータをACCESSに移行2. かみちゃん 08/7/31(木) 0:56 発言[未読]
【57194】Re:CSVデータをACCESSに移行2. satsuki 08/7/31(木) 11:23 質問[未読]
【57196】Re:CSVデータをACCESSに移行2. かみちゃん 08/7/31(木) 12:47 発言[未読]
【57201】Re:CSVデータをACCESSに移行2. satsuki 08/7/31(木) 14:26 質問[未読]
【57207】Re:CSVデータをACCESSに移行2. neptune 08/7/31(木) 21:52 回答[未読]
【57208】Re:CSVデータをACCESSに移行2. satsuki 08/8/1(金) 1:08 発言[未読]
【57192】Re:CSVデータをACCESSに移行2. neptune 08/7/31(木) 10:25 発言[未読]
【57193】Re:CSVデータをACCESSに移行2. satsuki 08/7/31(木) 11:13 発言[未読]
【57198】Re:CSVデータをACCESSに移行2. neptune 08/7/31(木) 13:33 発言[未読]
【57209】Re:CSVデータをACCESSに移行2. satsuki 08/8/1(金) 1:14 発言[未読]
【57210】Re:CSVデータをACCESSに移行2. かみちゃん 08/8/1(金) 7:14 発言[未読]
【57222】Re:CSVデータをACCESSに移行2. satsuki 08/8/1(金) 19:37 質問[未読]
【57220】Re:CSVデータをACCESSに移行2. neptune 08/8/1(金) 16:18 発言[未読]
【57221】Re:CSVデータをACCESSに移行2. satsuki 08/8/1(金) 19:31 質問[未読]
【57225】Re:CSVデータをACCESSに移行2. かみちゃん 08/8/1(金) 21:28 発言[未読]
【57230】Re:CSVデータをACCESSに移行2. satsuki 08/8/2(土) 1:14 お礼[未読]
【57231】Re:CSVデータをACCESSに移行2. かみちゃん 08/8/2(土) 9:56 発言[未読]
【57232】Re:CSVデータをACCESSに移行2. neptune 08/8/2(土) 11:08 発言[未読]
【57227】Re:CSVデータをACCESSに移行2. neptune 08/8/1(金) 22:20 発言[未読]
【57244】Re:CSVデータをACCESSに移行2. satsuki 08/8/2(土) 18:12 お礼[未読]

【57168】CSVデータをACCESSに移行2.
質問  satsuki  - 08/7/30(水) 16:13 -

引用なし
パスワード
   こんにちは、Satsukiと申します。
前回の続きですが、今度は別のところで行き詰まりました。
どなたかご教示お願いいたします。

For〜next文の間で下記のように1行ずつ下へフォーカスをずらして、
新しいタイトルが出てきたら、それぞれ変数にタイトルとテーブル名を入れるようにしたいのですが、
ActiveCell.Value = Title(i + 1)
のところで、iが2以上になると配列の値がなくなるので、
「インデックスが有効範囲にありません」というエラーが出ます。
何かよい方法はありますでしょうか?

Title(0) = "1.店別来店数"
Title(1) = "2.店別製品別売上数"
Title(2) = "3.店別個人別売上数"

TableName(0) = "raiten"
TableName(1) = "seihinbetsu"
TableName(2) = "kojinbetsu

TitleName = Title(0)
InputTable = TableName(0)

  Cells(j, 1).Activate

  If ActiveCell.Value = Title(i + 1) Then
    TitleName = Title(i + 1)
    InputTable = TableName(i + 1)
    i = i + 1
  End If

(補足)↓↓↓↓↓↓↓↓↓↓↓↓↓↓
CSVファイルで下記のようなリストがあり、各タイトルごとにテーブルを分けてACCESSに出力しようとしています。

1.店別来店数
A店  550
B店  360
C店  480

2.店別製品別売上数
A店
 製品1 15
 製品2 26
B店
 製品1 28
 製品3 45
C店
 製品2 35
 製品4 12

3.店別個人別売上数
A店
 製品1 
  担当A 6
  担当B 9
 製品2
  担当B 6
  担当C 20 
B店
 製品1 
  担当D 9
  担当E 15
  担当F 4
 製品3
  担当D 24
  担当E 21
C店
 製品2
  担当G 7
  担当H 12
  担当F 16
 製品4 
  担当G 2
  担当H 7
  担当F 3

【57183】Re:CSVデータをACCESSに移行2.
発言  neptune  - 08/7/30(水) 22:31 -

引用なし
パスワード
   ▼satsuki さん:
こんにちは

Resが付いてないようなので。
>ActiveCell.Value = Title(i + 1)
>のところで、iが2以上になると配列の値がなくなるので、
>「インデックスが有効範囲にありません」というエラーが出ます。
>何かよい方法はありますでしょうか?
良い方法も何も、エラーメッセージそのままの対応をすればよいだけです。
インデックスの有効範囲である事を確認してやるか、保障してやればよいだけ
です。

で、そんな事は枝葉末節な事で、CSVファイルを読み込んで、必要なデータの並び
にデータを整形する事はできますか?
「CSVデータをACCESSに移行」にExcelのシートは全く必要なく、使っても
良いですが、別のCSVファイルにデータを整形して移すとか、現在のCSV
を読み込み、データ整形をしながら、mdbに流し込むとか色んな方法が
あります。
どんな方法をとっても、
「CSVファイルを読み込んで、必要なデータの並びにデータを整形するスキル」
は必要になります。これにはCSVファイルを読み込んで、文字列操作をすると言う
事が必要です。
失礼かもしれませんが、この辺りは大丈夫ですか?

【57188】Re:CSVデータをACCESSに移行2.
質問  satsuki  - 08/7/31(木) 0:47 -

引用なし
パスワード
   ▼neptune さん:
レスありがとうございます。

エラーメッセージの対応を工夫してみましたが、上手く行きませんでした。
スキル不足でしょうか?
以前、こちらのサイトで、ネットやテキストでは探しきれないような、とても賢い方法をご紹介いただいて、大変勉強になりましたので、今回も、きっともっと賢いやり方があるのではないかと思い、質問させて頂きました。
この仕事自体もまだ実際に受けた訳ではなく、勉強のためにやり始めています。

エクセルで最終的に一覧表にするとのことなので、エクセルでVBAを書こうと思いましたが、他のやり方の方がいいでしょうか?


>▼satsuki さん:
>こんにちは
>
>Resが付いてないようなので。
>>ActiveCell.Value = Title(i + 1)
>>のところで、iが2以上になると配列の値がなくなるので、
>>「インデックスが有効範囲にありません」というエラーが出ます。
>>何かよい方法はありますでしょうか?
>良い方法も何も、エラーメッセージそのままの対応をすればよいだけです。
>インデックスの有効範囲である事を確認してやるか、保障してやればよいだけ
>です。
>
>で、そんな事は枝葉末節な事で、CSVファイルを読み込んで、必要なデータの並び
>にデータを整形する事はできますか?
>「CSVデータをACCESSに移行」にExcelのシートは全く必要なく、使っても
>良いですが、別のCSVファイルにデータを整形して移すとか、現在のCSV
>を読み込み、データ整形をしながら、mdbに流し込むとか色んな方法が
>あります。
>どんな方法をとっても、
>「CSVファイルを読み込んで、必要なデータの並びにデータを整形するスキル」
>は必要になります。これにはCSVファイルを読み込んで、文字列操作をすると言う
>事が必要です。
>失礼かもしれませんが、この辺りは大丈夫ですか?

【57189】Re:CSVデータをACCESSに移行2.
発言  かみちゃん E-MAIL  - 08/7/31(木) 0:56 -

引用なし
パスワード
   こんにちは。かみちゃん です。

横から失礼します。

>エラーメッセージの対応を工夫してみましたが、上手く行きませんでした。
>スキル不足でしょうか?

スキル不足というより、説明不足です。
どのように工夫されて、どのように上手くいかないのかを説明することはできませんか?

> エクセルで最終的に一覧表にするとのこと

私も、ExcelVBAで、Accessのデータをエクスポートしたりインポートしたりして、
似たようなことをしています。

【57192】Re:CSVデータをACCESSに移行2.
発言  neptune  - 08/7/31(木) 10:25 -

引用なし
パスワード
   ▼satsuki さん、かみちゃんさん
こんにちは

>「CSVファイルを読み込んで、必要なデータの並びにデータを整形するスキル」
>は必要になります。これにはCSVファイルを読み込んで、文字列操作をすると言う
>事が必要です。
>失礼かもしれませんが、この辺りは大丈夫ですか?
の返事が無いのですが、前回のスレッドで、VBにおける文字列処理の基本を
見落としているのでVBAだけではなく、プログラミング経験そのものが余り無い
のかも?判断します。

但し、
>この仕事自体もまだ実際に受けた訳ではなく、勉強のためにやり始めています。
との記述がある為、仕事としてプログラムを書く必要の有る方と判断します。

で、本題ですが、
本スレッドの最初のサンプルソースで、for~next文を使用していると書いている
にも関わらず、for~next文におけるi、jの初期値、最終値の設定が書かれていない
ので正確には判断できない。従って、
>インデックスの有効範囲である事を確認してやるか、保障してやればよいだけ
というアドバイスになります。
(有る程度の経験があるならこれで十分な答えです。)

その後
>エラーメッセージの対応を工夫してみましたが、上手く行きませんでした。
>スキル不足でしょうか?
という進展状況を書かれましたが、どの様な工夫かを明記していない為
少なくとも質問、アドバイスを求めるスキルは不足していると思います。

>エクセルで最終的に一覧表にするとのことなので、エクセルでVBAを書こうと
>思いましたが、他のやり方の方がいいでしょうか?
どの言語でもやる事は同じと思います。なので、↑に付いては自分で理解、
判断できる方法が良いとしか申し上げられません。

どの言語でも、「CSVファイルで下記のようなリストがあり、各タイトルごとにテーブルを分けてACCESSに出力」
という目的ならExcelVBAも含め、現在のやり方がBestとは思いません。
ご自分の得意な言語と同じやり方でどうぞ。言語により当然多少手続きは
違うでしょうが、同じ事ができると思います。
・・実はつい最近自分用で、ExcelVBAではないですが、TextファイルをAccessに落としました。今回と殆ど同じ事です。^ ^;

但し、自分で理解、判断できる方法と言う事は同じです。でないと後でUserさん
からの改造依頼、サポート、などの必要性が発生した際、大変な事になります。

誰が読んでも判るような説明+再現性の有るサンプルソースをUPすれば
もっと、良いアドバイスを受けられると思いますし、私より親切な方からも
アドバイスを受けられると思いますよ。

例えば、このスレにも書き込んでくれているかみちゃんさんは私よりかなり
親切です。

#かみちゃんさんお久しぶりです。こう↑書いたからと言って無理しないで下さいね。

あっ後、satsuki さんにお願い
無用な引用は止めて下さい。スレッドが長くなり見にくいだけですから。

【57193】Re:CSVデータをACCESSに移行2.
発言  satsuki  - 08/7/31(木) 11:13 -

引用なし
パスワード
   ▼neptune さん:
レスありがとうございます。
そのスレッド(特にプログラムの部分)が長くなり読みにくくならないようにしようと思って、プログラムの抜粋だけを書きましたが、逆に説明不足だったのですね。申し訳ありません。

>前回のスレッドで、VBにおける文字列処理の基本を
>見落としているのでVBAだけではなく、プログラミング経験そのものが余り無い
>のかも?判断します。

経験は決して長くないです。

>本スレッドの最初のサンプルソースで、for~next文を使用していると書いている
>にも関わらず、for~next文におけるi、jの初期値、最終値の設定が書かれていない
>ので正確には判断できない。

最初に一つめのタイトルのあるセルを検索し、↓
SearchWord = TitleName(0)
Set kiten2 = Worksheets("Sheet1").Columns(1).Find(What:=SearchWord, LookIn:=xlValues, LookAt:=xlWhole)

そのセルからデータの最終行までを最終値にしています。
For j = kiten2.Row + 1 To Range("A65536").End(xlUp).Row

>という進展状況を書かれましたが、どの様な工夫かを明記していない為
>少なくとも質問、アドバイスを求めるスキルは不足していると思います。

下記のようなコードをいれましたが、そうすると、「3.店別個人別売上数」
より下を見に行かずにおわってしまいました。
If i > 1 Then
  Exit Sub
End If

>ExcelVBAも含め、現在のやり方がBestとは思いません。
>ご自分の得意な言語と同じやり方でどうぞ。言語により当然多少手続きは
>違うでしょうが、同じ事ができると思います。
>・・実はつい最近自分用で、ExcelVBAではないですが、TextファイルをAccessに落としました。今回と殆ど同じ事です。^ ^;

いえいえ、言語はVBAを使うのですが、コーディングの仕方がもっといい方法はないかと思い、ご質問いたしました。

>誰が読んでも判るような説明+再現性の有るサンプルソースをUPすれば
>もっと、良いアドバイスを受けられると思いますし、私より親切な方からも
>アドバイスを受けられると思いますよ。

全部コードを書くのは読むのが疲れるかなと思いましたが、必要な部分も足りなかったようですね。ご指摘ありがとうございました。

【57194】Re:CSVデータをACCESSに移行2.
質問  satsuki  - 08/7/31(木) 11:23 -

引用なし
パスワード
   ▼かみちゃん さん:

レスありがとうございます。
また、前回はおかげさまで解決いたしました。ありがとございました。

>スキル不足というより、説明不足です。
>どのように工夫されて、どのように上手くいかないのかを説明することはできませんか?

申し訳ありません。説明不足だったのですね。
書いて説明するほどの工夫とも言えず、お恥ずかしいのですが。
下記のようなコードをいれました。そうすると、「3.店別個人別売上数」
より下を見に行かずにおわってしまいました。
If i > 1 Then
  Exit Sub
End If

jの初期値と最終値の設定は下記のようです。
最初に一つめのタイトルのあるセルを検索し、↓
SearchWord = TitleName(0)
Set kiten2 = Worksheets("Sheet1").Columns(1).Find(What:=SearchWord, LookIn:=xlValues, LookAt:=xlWhole)

そのセルからデータの最終行までを最終値にしています。
For j = kiten2.Row + 1 To Range("A65536").End(xlUp).Row

>私も、ExcelVBAで、Accessのデータをエクスポートしたりインポートしたりして、
>似たようなことをしています。

経験のある方のアドバイスをぜひよろしくお願いいたします。

【57196】Re:CSVデータをACCESSに移行2.
発言  かみちゃん E-MAIL  - 08/7/31(木) 12:47 -

引用なし
パスワード
   こんにちは。かみちゃん です。

> 全部コードを書くのは読むのが疲れるかなと思いました

いえ、実行できるコードが掲載されていれば、少なくとも、私は、シートなどサンプル
データなどの環境を用意して、まずは、テストしてみるようにしています。
そのため、いろいろな掲示板で、シートレイアウト、サンプルデータ、現在のコード、
期待している結果を示していただくようお願いしています。

> 下記のようなコードをいれました。そうすると、「3.店別個人別売上数」
> より下を見に行かずにおわってしまいました。
> If i > 1 Then
>   Exit Sub
> End If
>
> jの初期値と最終値の設定は下記のようです。
> 最初に一つめのタイトルのあるセルを検索し、↓
> SearchWord = TitleName(0)
> Set kiten2 = Worksheets("Sheet1").Columns(1).Find(What:=SearchWord, LookIn:=xlValues, LookAt:=xlWhole)
>
> そのセルからデータの最終行までを最終値にしています。
> For j = kiten2.Row + 1 To Range("A65536").End(xlUp).Row

変数 i と j の関係がよくわかりません。
お手数ですが、長くなってもいいので、コード全体を差し支えない程度に掲載していただ
くことはできませんか?

▼neptuneさん

> 例えば、このスレにも書き込んでくれているかみちゃんさんは私よりかなり
> 親切です。
>
> #かみちゃんさんお久しぶりです。こう↑書いたからと言って無理しないで下さいね。

おひさしぶりです。Acceessとの連携を得意とするneptuneさんにこのように言われると
恐縮です。
私は、特に初心者のころは、掲示板等でいろいろな方に親切にしていただき、そのおかげ
で、少しくらいは、VBAがわかってきたかな?という程度です。そのため、経験してい
ることは、できるだけ、親切にして、お役に立てたらいいなと思っています。
一緒に勉強していければ、うれしいですね。

今後ともよろしくお願いします。

【57198】Re:CSVデータをACCESSに移行2.
発言  neptune  - 08/7/31(木) 13:33 -

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


私は殆ど想像してまではサンプル書かないんですが、材料が少し増えたんで、
書いてみました。

こんな感じですか????
  '最初に一つめのタイトルのあるセルを検索し、↓
  SearchWord = TitleName(0)
  Set kiten2 = Worksheets("Sheet1").Columns(1).Find(What:=SearchWord, LookIn:=xlValues, LookAt:=xlWhole)
  
  Dim objsheet As Worksheet
  'そのセルからデータの最終行までを最終値にしています。
'  Worksheets("Sheet1")のセルに対して処理をすると仮定すると
  Set objsheet = Worksheets("Sheet1")

  'iは0から2の3要素という事を保障する
  For i = 0 To 2
    'kiten2は正常に取得できていると仮定して。
    '出来るだけマジックナンバーは避けましょう。
    For j = kiten2.Row + 1 To objsheet.Rows.Count
      'Cellsだけだと、その時のactiveなシートを指すので、シートを明示的に指示しよう
      If objsheet.Cells(j, 1).Value = Title(i) Then
        TitleName = Title(i)
        InputTable = TableName(i)
      End If
      'なんかの処理?Title(i),TableName(i)をそのまんま使っても良いのでは?
    Next j
  Next i

>言語はVBAを使うのですが、コーディングの仕方がもっといい方法はないかと思い、ご質問いたしました。
自分が質問するのに「ご」はいりませんよ^ ^;

で、本題ですが、上に書いたサンプルの部分にそっくりそのまま、ユーザー定義型
等の変数にデータを代入するとかして、そのまんまmdbに対して、データ追加の
SQLを投げるとか、mdbにパラメータクエリがあったら、それをキックするとか
の方法が「もっといい方法」と思います。
Excelのシートに代入すると言うものすごく重い処理をする必要は無いです。
と言うより、処理を重くするだけと思う。
Excelでの表示が必要なら、mdbから必要な部分を抽出してそれを表示すればよい。

後、現在のCSVをテーブルごとに複数のCSVに分け、そのまんま、それをSQLで
mdbに流し込むとか(出来るかどうかは未確認)、recordset取得してmdbに流し
込む(これは出来る)とかが思いつきます。

【57201】Re:CSVデータをACCESSに移行2.
質問  satsuki  - 08/7/31(木) 14:26 -

引用なし
パスワード
   ▼かみちゃん さん:
レスありがとうございます。

>変数 i と j の関係がよくわかりません。
>お手数ですが、長くなってもいいので、コード全体を差し支えない程度に掲載していただ
>くことはできませんか?

ありがとうございます。では、お言葉に甘えまして書かせて頂きます。
実際のデータを出すことはできませんので、同じパターンのデータを例にしてみました。前回はわかりやすくインデントして書きましたが、実際はすべてA列B列に表示されています。
1日ごとにCSVデータが出力され、各行に日付を入れて1件のデータにしていこうとしています。最終的には項目と日付のクロス集計をACCESSから出力します。

データ処理日
2008年7月15日

1.店別来店数
A店  550
B店  360
C店  480

2.店別製品別売上数
A店
製品1 15
製品2 26
B店
製品1 28
製品3 45
C店
製品2 35
製品4 12

3.店別個人別売上数
A店
製品1 
担当A 6
担当B 9
製品2
担当B 6
担当C 20 
B店
製品1 
担当D 9
担当E 15
担当F 4
製品3
担当D 24
担当E 21
C店
製品2
担当G 7
担当H 12
担当F 16
製品4 
担当G 2
担当H 7
担当F 3


Dim SearchWord As String
Dim kiten As Range
Dim kiten2 As Variant
Dim hiduke as string
Dim tenpo As String
Dim shohin As String
Dim i As Integer
Dim j As Integer

Dim Title(2) As String
Dim TitleName As String
Dim TableName(2) As String
Dim InputTable As String

Dim CN As ADODB.Connection
Dim RS As ADODB.Recordset
Dim strSQL As String

Dim hiduke As String

Set CN = New ADODB.Connection
CN.provider = "Microsoft.Jet.OLEDB.4.0"
CN.Open "C:\My Documents\bunseki.mdb"

Title(0) = "1.店別来店数"
Title(1) = "2.店別製品別売上数"
Title(2) = "3.店別個人別売上数"

TableName(0) = "raiten"
TableName(1) = "seihinbetsu"
TableName(2) = "kojinbetsu

Range("A1").Select

SearchWord = "*年*月*日*"
Set kiten = Worksheets("Sheet1").Columns(1).Find(What:=SearchWord, LookIn:=xlValues, LookAt:=xlWhole)

If Not kiten Is Nothing Then
  hiduke = kiten
End If

TitleName = Title(0)
InputTable = TableName(0)
i = 0

SearchWord = Title(0)
Set kiten2 = Worksheets("Sheet1").Columns(1).Find(What:=SearchWord, LookIn:=xlValues, LookAt:=xlWhole)
If kiten2 Is Nothing Then
  Exit Sub
End If

For j = kiten2.Row + 1 To Range("A65536").End(xlUp).Row
  Cells(j, 1).Activate
  ↓空白セルはとばす。
  If IsNull(ActiveCell.Value) Or ActiveCell.Value = "" Then
    Cells(j + 1, 1).Activate
    j = j + 1
  End If
  ↓タイトル行が出てきたら、変数に入れて、1行下にフォーカスをずらす。
  If ActiveCell.Value = Title(i + 1) Then
    TitleName = Title(i + 1)
    InputTable = TableName(i + 1)
    Cells(j + 1, 1).Activate
    i = i + 1
    j = j + 1
  End If
  ↓1件ごとのデータに共通の値を変数で保持。
  If ActiveCell.Value Like "*店" Then
    tenpo = Cells(j, 1)
  ElseIf ActiveCell.Value Like "製品*" Then
    shohin = Cells(j, 1)
  Else
    Set RS = New ADODB.Recordset
    strSQL = "select * from " & InputTable
    
    RS.Open strSQL, CN, adOpenStatic, adLockOptimistic, adCmdText
        
    Select Case TitleName
    Case "1.店別来店数"
      RS.addnew
        RS!日付 = kiten
        RS!店名 = Cells(j, 1).Value
        RS!人数 = Cells(j, 2).Value
      RS.Update
    Case "2.店別製品別売上数"
      RS.addnew
        RS!日付 = kiten
        RS!店名 = tenpo
        RS!製品名 = Cells(j, 1).Value
        RS!台数 = Cells(j, 2).Value
      RS.Update
    Case "3.店別個人別売上数"
      RS.addnew
        RS!日付 = kiten
        RS!店名 = tenpo
        RS!製品名 = shohin
        RS!担当名 = Cells(j, 1).Value
        RS!台数 = Cells(j, 2).Value
      RS.Update
     End Select
  End If
  
Next j

RS.Close
CN.Close

End Sub


全く別のやり方でも構いません。もっといい方法がありましたら、ご教授よろしくお願いいたします。

【57207】Re:CSVデータをACCESSに移行2.
回答  neptune  - 08/7/31(木) 21:52 -

引用なし
パスワード
   ▼satsuki さん:
こんにちは

なんか前に書いた奴が全くの無駄だったような・・・

>全く別のやり方でも構いません。もっといい方法がありましたら、ご教授よろしくお願いいたします。
という事で、データがUPされたようなデータならやっぱり先に書いた

>上に書いたサンプルの部分にそっくりそのまま、ユーザー定義型
>等の変数にデータを代入するとかして、そのまんまmdbに対して、データ追加の
>SQLを投げるとか、mdbにパラメータクエリがあったら、それをキックするとか
>の方法が「もっといい方法」と思います。
>Excelのシートに代入すると言うものすごく重い処理をする必要は無いです。
>と言うより、処理を重くするだけと思う。
>Excelでの表示が必要なら、mdbから必要な部分を抽出してそれを表示すればよい。
をお勧めします。

ADOの方に付いてはこれが実際かどうか不明だし、練習用でなんとも
言えませんので言及は止めておきます。

Excelの方で気づいた事ですが、
上記オブジェクトを省いたRange("A1")とかcellsとか
ActiveCellなどは使わない癖を付けたほうが変なバグの元を防げます。

【57208】Re:CSVデータをACCESSに移行2.
発言  satsuki  - 08/8/1(金) 1:08 -

引用なし
パスワード
   ▼neptune さん:

>なんか前に書いた奴が全くの無駄だったような・・・

無駄ではございません。
説明不足だったかも知れませんが、EXCELにデータを読み込むのは暫定的なもので、後でCSVを直接読む方法を調べようと思っておりました。
お教え頂いた方法で読み込めました。ありがとうございました。

ただ、
For i = 0 To 2
 ・
 ・
next i
の部分は上手く適合しません。(これは実は自分でもやってみました。)
この部分が解決していないので、前に進めません。

>ADOの方に付いてはこれが実際かどうか不明だし、練習用でなんとも
>言えませんので言及は止めておきます。

ADOの部分は実際のとおりです。練習用にしたのは例題だけです。

>Excelの方で気づいた事ですが、
>上記オブジェクトを省いたRange("A1")とかcellsとか
>ActiveCellなどは使わない癖を付けたほうが変なバグの元を防げます。

ご指摘ありがとうございます。
フォルダの中にあるすべてのCSVファイルを順次読み込む形にしていくのが次の段階にやる事なので、オブジェクト名は必要ですね。

【57209】Re:CSVデータをACCESSに移行2.
発言  satsuki  - 08/8/1(金) 1:14 -

引用なし
パスワード
   ▼neptune さん:
レスありがとうございました。
もうひとつの方に先にレスしてしまいましたが、サンプルの一部を自分のコードに埋め込んで、CSVを読み込むようにできました。ありがとうございました。

>For j = kiten2.Row + 1 To objsheet.Rows.Count
ここでは、「オーバーフローしました」というエラーがでました。

>Title(i),TableName(i)をそのまんま使っても良いのでは?
私もそう思い始めております。

>Excelのシートに代入すると言うものすごく重い処理をする必要は無いです。
>と言うより、処理を重くするだけと思う。
EXCELのシートに代入すると重い処理になるのですね。

>後、現在のCSVをテーブルごとに複数のCSVに分け、そのまんま、それをSQLで
>mdbに流し込むとか(出来るかどうかは未確認)、recordset取得してmdbに流し
>込む(これは出来る)とかが思いつきます。

そのあたりの方法に大変興味があります。

【57210】Re:CSVデータをACCESSに移行2.
発言  かみちゃん E-MAIL  - 08/8/1(金) 7:14 -

引用なし
パスワード
   こんにちは。かみちゃん です。

取り急ぎ。

>>For j = kiten2.Row + 1 To objsheet.Rows.Count
>ここでは、「オーバーフローしました」というエラーがでました。

Dim i As Integer
と宣言していませんか?
そのように宣言していると、i が32767を超えると、上記のエラーが出ます。
objsheet.Rows.Count が、いくつになるかを考えてみてください。

対処としては、
Dim i As Long
としてみてはいかがでしょうか?
行番号を示す変数の場合は、Long 型にしたほうがいいです。

【57220】Re:CSVデータをACCESSに移行2.
発言  neptune  - 08/8/1(金) 16:18 -

引用なし
パスワード
   ▼satsuki さん:
こんにちは


>>For j = kiten2.Row + 1 To objsheet.Rows.Count
>ここでは、「オーバーフローしました」というエラーがでました。
ウォッチウィンドウか、ローカルウィンドウでその時のデータを確認しましょう。
取り合えず、ここはかみちゃんさんのご指摘を試してみて下さい。

>>後、現在のCSVをテーブルごとに複数のCSVに分け、そのまんま、それをSQLで
>>mdbに流し込むとか(出来るかどうかは未確認)、recordset取得してmdbに流し
>>込む(これは出来る)とかが思いつきます。

>そのあたりの方法に大変興味があります。
ですが、CSVファイルのデータを良く見ると、1つのファイルに複数のテーブル
が含まれているようですので、上記の提案は不向きですね。ファイル内の
データを解析したら、それをそのまんまmdbに放り込むほうが楽チンです。

知っているかどうか判らないので一応書いておきますが、CSVファイルも
DAO、ADOを使用して、検索、追加は出来ます。
削除は出来ない(ファイル操作では可能)。
変更も多分出来ない。これは忘れました。これもファイル操作では可能です。
CSVファイルは1行目がテーブル名になっていることが必要です。

構造としては、ディレクトリがDB、1ファイルが1テーブルとみなします。
ググッたら沢山サンプルがあると思います。

その他気付いた点
・DBへの追加処理は、別プロシージャにした方が見易い
(好みだけの問題ではない。メンテナンス性。)
・RS.Open 後、RSを閉じないまま次のものに使っているが、問題は生じないんですかね?
 (問題ないとは思いますが、こういう方法を取った事無いので知りません。)
・recordsetを開く際、openメソッドの第1引数でTable名を指定して、
第4引数でadCmdTableを指定すれば無駄なSQLを投げる必要は無かったと思う。

【57221】Re:CSVデータをACCESSに移行2.
質問  satsuki  - 08/8/1(金) 19:31 -

引用なし
パスワード
   ▼neptune さん:
レスありがとうございます。

>>>For j = kiten2.Row + 1 To objsheet.Rows.Count
>ウォッチウィンドウか、ローカルウィンドウでその時のデータを確認しましょう。
>取り合えず、ここはかみちゃんさんのご指摘を試してみて下さい。

これは、データ見ました。65536がでました。
そして、かみちゃんさんのご指摘を試してみましたら、エラーは出ないまま65536回繰り返す状態になりました。
エクセルシートを使った時の
Range("A65536").End(xlUp).Row
はそのまま使えたのですが、これではまずいでしょうか?

>CSVファイルのデータを良く見ると、1つのファイルに複数のテーブル
>が含まれているようですので、上記の提案は不向きですね。ファイル内の
>データを解析したら、それをそのまんまmdbに放り込むほうが楽チンです。

今の状態がその楽チンな方法と考えてよいですか?


>知っているかどうか判らないので一応書いておきますが、CSVファイルも
>DAO、ADOを使用して、検索、追加は出来ます。
>削除は出来ない(ファイル操作では可能)。
>変更も多分出来ない。これは忘れました。これもファイル操作では可能です。
>CSVファイルは1行目がテーブル名になっていることが必要です。

ご教示ありがとうございます。

>その他気付いた点
>・DBへの追加処理は、別プロシージャにした方が見易い
>(好みだけの問題ではない。メンテナンス性。)

これは後で修正してみます。

>・RS.Open 後、RSを閉じないまま次のものに使っているが、問題は生じないんですかね?

RS.close をnext j の上に入れてみましたが、
RS.closeのところで「オブジェクトが閉じている時は操作は許可されません」というエラーがでましたので、RS.UPDATEの直後に毎回入れました。
RS.closeの入れ場所がまずいですか?

>・recordsetを開く際、openメソッドの第1引数でTable名を指定して、
> 第4引数でadCmdTableを指定すれば無駄なSQLを投げる必要は無かったと思う。

RS.Open InputTable, CN, adOpenKeyset, adLockOptimistic, adCmdTable
に変更し、上手く作動しました。

【57222】Re:CSVデータをACCESSに移行2.
質問  satsuki  - 08/8/1(金) 19:37 -

引用なし
パスワード
   ▼かみちゃん さん:

>Dim i As Integer
>と宣言していませんか?
>そのように宣言していると、i が32767を超えると、上記のエラーが出ます。
>objsheet.Rows.Count が、いくつになるかを考えてみてください。

j の値は65536がでます。
なので、オーバーフローしないようにDim j as Longに変えると
65536回操作を繰り返します。
エクセルシートのときの
Range("A65536").End(xlUp).Row
を今回のCSVシートにも使うとデータ最終行が検知されます。

【57225】Re:CSVデータをACCESSに移行2.
発言  かみちゃん E-MAIL  - 08/8/1(金) 21:28 -

引用なし
パスワード
   こんにちは。かみちゃん です。

>エクセルシートを使った時の
>Range("A65536").End(xlUp).Row
>はそのまま使えたのですが、これではまずいでしょうか?

Integer型で宣言している変数に格納する場合で、
Range("A65536").End(xlUp).Row
の戻り値が32767以下の場合は、問題ありません。

しかし、それを超える場合は、「オーバーフロー」になります。
そのため、Long型で宣言するのです。

なお、
Range("A65536").End(xlUp).Row
は、A列の値が入っている最終行ですので、それが32767行より上か下によって
違うのですが、
Long型で宣言していれば、気にすることはなくなると思います。

【57227】Re:CSVデータをACCESSに移行2.
発言  neptune  - 08/8/1(金) 22:20 -

引用なし
パスワード
   ▼satsuki さん:
こんにちは

私ならこんな感じと言うのを格好と流れだけ書いてみました。
でも、大体こんな感じ。

Private Enum TargetTableName
  店別来店数
  店別製品別売上数
  店別個人別売上数
End Enum

Private Type RecordData
  日付 As Date
  店名 As String
  人数 As Long
  製品名 As String
  担当名 As String
  台数 As Long
End Type

Private Sub InsertMain()
Dim Cn As ADODB.Connection
Dim cnString As String
Dim typData() As RecordData
Dim fNum As Long
Dim Ret As Boolean
Const csvpath As String = "E:\Data\Office\Access\TestData.csv"

  On Error GoTo ErrTrap
  Set Cn = New ADODB.Connection
  cnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\hogehogeDirctory\Test.mdb;" '後必要な引数加える
  Cn.ConnectionString = cnString
  Cn.Open
  
  '/////////私なら多分読み取り部分も別Functionにすると思う///////////
  fNum = FreeFile()
  'データが数MBなら全部読み込んでおく
'  ファイルオープン
'  全データ取得
'  ファイルクローズ
  'ここで必要なデータだけを取得してtypDataに入れる
  '//////////////////////////////////////////////////////////////////
  
  Ret = InSertData(店別来店数, typData, Cn)
  'データの数だけ繰り返す
  
  
  Cn.Close
  Set Cn = Nothing
  Exit Sub
ErrTrap:
  '必要なエラー処理
End Sub

Private Function InSertData(ptbl As TargetTableName, pRec() As RecordData, pCn As ADODB.Connection) As Boolean
  Dim sSQL As String
  Dim Cmd As ADODB.Command
  '引数チェック
  '手抜き
  
  '例えばSQLを投げる
  sSQL = "INSERT INTO "
  'SQL生成
  Select Case ptbl
    Case TargetTableName.店別来店数
      '個別のSQL生成
      sSQL = sSQL & TargetTableName & "(日付,店名,人数)" & _
          " VALUES(#" & pRec.日付 & "#,'" & pRec.店名 & "'," & pRec.人数 & ")"
    Case TargetTableName.店別個人別売上数
    Case TargetTableName.店別製品別売上数
  End Select
'  Commandオブジェクト生成
  'command実行
  
'  '例えばパラメータクエリをキックする
'  '私は大概こちらの方法をとります。
'  Select Case ptbl
'    Case TargetTableName.店別来店数
'       'パラメータ生成、パラメータにデータ入力
'    Case TargetTableName.店別個人別売上数
'    Case TargetTableName.店別製品別売上数
'  End Select
'  'command実行
  'commandオブジェクトの後始末
End Function

後、VBでInteger型を使うメリットはありません。最近のパソコンは
32bitか64bitですから最低でもそのメモリは消費しますから。ですから、
VBではintegerよりlongの方が無駄な変換がないだけ効率的らしいです。

【57230】Re:CSVデータをACCESSに移行2.
お礼  satsuki  - 08/8/2(土) 1:14 -

引用なし
パスワード
   ▼かみちゃん さん:
レスありがとうございます。

宣言はLong型ですれば安全なのですね。
ところで、現象としては、
For j = kiten2.Row + 1 To objsheet.Rows.Count
だとデータの最終行ではなく、シートの最終行(65536行目)を検知しているようです。

>Range("A65536").End(xlUp).Row
>は、A列の値が入っている最終行
ということは、A列だけしか見ないので、まずいですよね。

For j = kiten2.Row + 1 To objsheet.Cells(Rows.Count, 1).End(xlUp).Row
ネットで調べて上記のようにやってみたら、422行目(最終行)を検知しました。

【57231】Re:CSVデータをACCESSに移行2.
発言  かみちゃん E-MAIL  - 08/8/2(土) 9:56 -

引用なし
パスワード
   こんにちは。かみちゃん です。

>宣言はLong型ですれば安全なのですね。

安全というか、その変数に格納される最大値が何かをよく考えて、使う必要があります。
ただ、neputuneさんもおっしゃっていますが、
> 後、VBでInteger型を使うメリットはありません。最近のパソコンは
> 32bitか64bitですから最低でもそのメモリは消費しますから。ですから、
> VBではintegerよりlongの方が無駄な変換がないだけ効率的
というのは、私もそう思います。

>ところで、現象としては、
>For j = kiten2.Row + 1 To objsheet.Rows.Count
>だとデータの最終行ではなく、シートの最終行(65536行目)を検知しているようです。

検知ではなく、objsheet.Rows.Count は、Excelシートの最大行を取得します。
Excel2003までは、常に65536です。
objsheet.Rows.Count

Range("A65536").End(xlUp).Row
は、まったく違います。

>>Range("A65536").End(xlUp).Row
>>は、A列の値が入っている最終行
>ということは、A列だけしか見ないので、まずいですよね。
>
>For j = kiten2.Row + 1 To objsheet.Cells(Rows.Count, 1).End(xlUp).Row
>ネットで調べて上記のようにやってみたら、422行目(最終行)を検知しました。

objsheet.Cells(Rows.Count, 1).End(xlUp).Row
は、objsheetのRows.Count行目の1列目(つまりA65536セル)から上方向に、値が
入っているセルの行を返します。
つまり、Excel2003までの場合は、
objsheet.Range("A65536").End(xlUp).Row
と同じです。

【57232】Re:CSVデータをACCESSに移行2.
発言  neptune  - 08/8/2(土) 11:08 -

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

かみちゃん さんが既にご説明下さってますが

>そのセルからデータの最終行までを最終値にしています。
>For j = kiten2.Row + 1 To Range("A65536").End(xlUp).Row
から私が↓に書き直したとき間違えてました。
>    '出来るだけマジックナンバーは避けましょう。
>    For j = kiten2.Row + 1 To objsheet.Rows.Count

確認できない状態なので確認してませんでした。すみません。
ちなみに、私ならこうするといった流れを書いたコードも勿論
確認できてませんので、ケアレスミスがあったらこれもごめんなさい。
・・・色んな処理例えばError処理などを手抜きしてますが、これは置いといて
という事で。^ ^;;

【57244】Re:CSVデータをACCESSに移行2.
お礼  satsuki  - 08/8/2(土) 18:12 -

引用なし
パスワード
   ▼neptune さん:
コーディングサンプルをご教示頂き、誠にありがとうございます。

ただ今、読み取り部分のコーディングを研究中です。

A店
製品1 
担当A 6
担当B 9
製品2
担当B 6
担当C 20 
 ↓
A店 製品1 担当A 6
A店 製品1 担当B 9
A店 製品2 担当B 6
A店 製品2 担当C 20

上記のように形を変えてtypDataに入れられるようにする部分が難しいため、
時間がかかりますので、改めてスレッド立てさせて頂きます。
また、わからないところがあったらよろしくお願いいたします。

>後、VBでInteger型を使うメリットはありません。最近のパソコンは
>32bitか64bitですから最低でもそのメモリは消費しますから。ですから、
>VBではintegerよりlongの方が無駄な変換がないだけ効率的らしいです。

ご教示ありがとうございます。これからはlongを使うように致します。

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