プロが教えるわが家の防犯対策術!

ACCESS DAO&VBA 初心者です。
どなたかお知恵を拝借いただけませんでしょうか。課題は以下の内容です。
諸事情(というか私の力量なんでしょうが)。納品店舗(列)とアイテム毎の発注数量(行)を、テーブルに格納しています。発注数量の合計がnull値の店舗を削除するコードを下記のように書きました。
Sub テスト()
Dim DB As Database
Dim Tdf As DAO.Recordset
Dim i As Integer
Dim s As Long
Dim g As Long
Dim tenn As String
Dim hinn As String
Set DB = CurrentDb
Set Tdf = DB.OpenRecordset("○○○ピッキングテーブル")

hinn = Tdf.fields(i)
i = 4
For i = Tdf.fields.Count - 1 To 4 Step -1
g = 0
Tdf.MoveFirst
Do Until Tdf.EOF
tenn = Tdf.fields(i).Name
'MsgBox tenn
s = Nz(Tdf.fields(i))
g = s + g
Tdf.MoveNext
Loop
If g = 0 Then
※Tdf.fields(i).Delete Tdf.fields(i).Name  実行時エラー 438でストップ
End If

Next
Set Tdf = Nothing: Set DB = Nothing

End Sub
  ※で実行時エラーの発生。
DAO の基本的な運用および設定の間違いのように思えるのですが、解消できません。どなたかよろしくお願いします。

質問者からの補足コメント

  • kenkenさん丁寧な返答ありがとうございます。
    私が削除したい列は、アイテム1,2,3すべての納品がない店舗です。そのため、OpenRecordset
    で、店舗毎の納品数量を精査させているつもりなんです。つまり、行の情報を精査させて、その結果で列を削除させるコードの書き方なんです。わがまま言って申し訳ありませんが、何らかの解決方法がありますでしょうか?ご指導ください。

      補足日時:2022/06/25 00:40

A 回答 (4件)

こんばんは。



ソースから何となく集計してるのかなーとは思っていましたが、、
こんな時は DSum や SQL の集計関数を利用します。

https://officek.net/access/a-function/al-dfunc/d …
https://www.ipentec.com/document/sql-get-sum

ソースがなるべく簡易になるように DSum 関数を使った例です。
コメントやエラートラップで長く見えますけど、シンプルなソースです。

Sub sampleProc()

  Const TABLE_NAME As String = "○○○ピッキングテーブル"

  Dim DB    As DAO.Database
  Dim table_def As DAO.TableDef
  Set DB = CurrentDb
  Set table_def = DB.TableDefs(TABLE_NAME)

  Dim i   As Long
  Dim total As Long
  
  ' i は列フィールドの番号(インデックス)
  ' 最後の列を除き、後ろから4列目に向かって逆順に処理
  For i = table_def.Fields.Count - 1 To 4 Step -1
    '
    Dim f  As DAO.Field
    Set f = table_def.Fields(i)

    ' Dsumなどの集計関数を使う方が楽
    total = Nz(DSum(f.Name, TABLE_NAME))
    
    If total = 0 Then
      ’ 合計値が0の時、列を削除する
      On Error Resume Next
      table_def.Fields.Delete f.Name
      ' テーブルが開いている=使用中だとエラー3211が発生
      If Err.Number = 3211 Then
        MsgBox "テーブル使用中エラー", vbCritical
        Exit Sub
      End If
      On Error GoTo 0
    End If

    Set f = Nothing
    ’
  Next

  Set table_def = Nothing
  Set DB = Nothing

End Sub
    • good
    • 0

補足します。


本ご質問は下記の問題点を含むと考えます。
レコードはひとつしかない?

■問題点1

列(フィールド)を削除する場合は注意が必要です。
添付図参照

削除 → アイテム1の行(レコード)で店舗Bは Null であるから列[店舗B]を削除
結果 → 店舗Bのアイテム2、アイテム3のデータが無かったことに

この点はどのように考えていますか?


■問題点2

>Set DB = CurrentDb
>Set Tdf = DB.OpenRecordset("○○○ピッキングテーブル")
>Tdf.fields(i).Delete Tdf.fields(i).Nam

この形で列を削除したいなら、Tdf は OpenRecorset ではなく次の様にします。

Dim db As DAO.Database: Set db = CurrentDb
Dim table_def As DAO.TableDef
Set table_def = db.TableDefs("○○○ピッキングテーブル")

'↓テーブルが開いてなければ、次のコードで列[店舗F]は削除できる
table_def.Fields.Delete "店舗F"

なお、TableDef は Table Define の略で、テーブル構造(どんな列を持つかなど)の定義オブジェクトです。

行の情報にアクセスできませんから、この方法でレコードの内容を精査しながらの列の削除は不可能です。

仮に OpenRecordset を併用し内容を精査できたとして、問題点1 が解決できません。
「ACCESS DAO で不要なテーブルの」の回答画像3
    • good
    • 2

こんにちは。


通常は列(カラム、フィールド)は削除しません。削除するなら行なのですが、、

https://docs.microsoft.com/ja-jp/office/client-d …

具体的にテーブルの内容を列名を1行目に、数レコード分を提示し、次にどの様な結果を望んでいるのかをまた同様に提示してみて下さい。

説明しにくい場合は、画像の添付も。
    • good
    • 1

ど素人でございますのでダメならスル~して下さい。



>Tdf.fields(i).Delete Tdf.fields(i).Name

Tdf.fields.Delete Tdf.fields(i).Name

ググって見つけたもの。
https://oshiete.goo.ne.jp/qa/9023032.html
    • good
    • 0

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

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