4

私のプロジェクトでは、テーブルとその下にある ListObjects および ListColumns をよく利用します。そのままの Range オブジェクトよりも参照と更新が簡単なので、私はそれらを気に入っています。それでも、多くの ListColumns で構成され、プロジェクト内のすべてのワークシートで参照される複数の ListObjects を処理する、適切で保守可能な方法をまだ見つけていません。

少数の列 (Column1、Column2、...、Column10) を持つテーブル (TableA) を含むワークシート ((Name) プロパティを "WorksheetA" に設定) があるとします。

ここで、別のワークシートのコードから列の 1 つを参照したいと考えています。私は次のようにそれを行うことができます:

WorksheetA.ListObjects("TableA").ListColumns("Column7")

メンテナンスが難しく、エラーが発生しやすいため、文字列を直接使用することはお勧めできません。

ならどうしよう?

文字列を定数として格納するための専用モジュールを作成できます。たとえば、「Constants」というモジュール:

Public Const TABLE_A As String = "TableA"
Public Const COLUMN7 As String = "Column7"

次に、私の参照は次のように変換できます。

WorksheetA.ListObjects(Constants.TABLE_A).ListColumns(Constants.COLUMN7)

ただし、このソリューションにはいくつかの欠点があります。

  1. 定数モジュールは、テーブルと列が追加されるたびに途方もなく速く成長します。
  2. 参照自体が大きくなり、読みにくくなります。
  3. すべてのワークブックのテーブルに関連するすべての定数は、1 つの巨大な穴に投げ込まれます。

WorksheetA 内に定数を格納し、次のようなパブリック関数を介して使用できるようにすることができます。

Private Const TABLE_A As String = "TableA"
Private Const COLUMN7 As String = "Column7"

Public Function GetTableAName() As String
    GetTableAName = TABLE_A
End Function

Public Function GetTableA() As ListObject
    Set GetTableA = WorksheetA.ListObjects(TABLE_A)
End Function

Public Function GetTableAColumn7() As ListColumn
    Set GetTableAColumn7 = GetTableA().ListColumns(COLUMN7)
End Function

このソリューションは実際には上記の 3 つの問題をすべて解決しますが、新しいテーブルを追加すると各列に関数を作成する必要があるため、まだ少し「汚い」上に時間がかかります。

この問題に対処する方法について、より良い考えがありますか?

EDIT1 (わかりやすくするため):ユーザーが名前を変更してはならない (テーブル名も列名も) と仮定しましょう。ユーザーがそうした場合、それはユーザーの責任です。

EDIT2 (わかりやすくするため):例として、Column7 を列名として使用しました。列にもっと意味のある名前があると仮定しましょう。

4

1 に答える 1

1

これが私の2セントです。私は教育を受けたプログラマーではありませんが、プログラマーとしての報酬を得ているので、それが私をプロにしていると思います。

防御の第一線は、テーブルをモデル化するためのクラスを作成することです。テーブルからクラスを埋めますが、他のコードはデータがどこにあるかさえ知りません。初期化すると、次のようなコードが実行されます

clsEmployees.FillFromListObject wshEmployees.ListObjects(1)

次に、クラスでは、コードは次のようになります

vaData = lo.DataBodyRange.Value
...
clsEmployee.EeName = vaData(i,1)
clsEmployee.Ssn = vaData(i,2) 
etc

ワークシートごとに 1 つの ListObject のみ。それが私のルールであり、決してそれを破ることはありません。ワークシートにアクセスできる人なら誰でも、列を並べ替えてコードを壊す可能性があります。Excel をデータベースとして使用したい場合 (場合によっては使用する場合)、それは私が負うリスクです。そのリスクを負うことができないほど重要な場合は、データを SQL Server、SQLite、または JET に保存します。

範囲を配列に入れる代わりに、実際に ListColumns の名前を呼び出すことができます。そうすれば、誰かが列を再配置しても、私のコードは引き続き機能します。しかし、列の名前を変更できることを紹介しているので、あるリスクを別のリスクと交換しているだけです。それはコードをより読みやすくするので、あなたがしたい取引かもしれません. 私は配列からの入力の速度が好きなので、それが私が行う取引です。

私のプロジェクトが十分に小さい場合、または ListObjects を直接操作することが想定されている場合は、すべての Strings の場合と同じ規則に従います。

  • コードで文字列を使用するのは 1 回だけです。
  • 複数回使用する場合は、プロシージャレベルの定数を作成します
  • 複数のプロシージャで使用する場合は、引数として渡すようにします
  • 引数として渡せない場合は、モジュール レベルの定数を作成します。
  • 2 つのプロシージャが異なるモジュールにある場合、まず、2 つのプロシージャが同じ定数を使用する異なるモジュールにある理由を自問します。関連する手順は同じモジュールにあるべきではありませんか?
  • 2 つのプロシージャが実際に異なるモジュールに属している場合は、それを引数として渡そうとします。
  • それが機能しない場合、それは本当にグローバル定数であり、MGlobals モジュールで設定します。

MGlobals が画面の約半分以上を占める場合は、何か間違ったことをしているので、一歩下がって、何を達成しようとしているのかをよく考える必要があります。そして、カスタムクラスを作成します。

于 2015-10-09T18:23:11.037 に答える