私は解決策を探すのに2日間費やしましたが、これは私を狂わせています...
まず、私が何をしているのかを説明させてください。50 万件のレコードを取り込み、これらのレコードが 12 個のピボット テーブルを動かしています。ワークブックを扱いやすいファイル サイズに保つために、ピボット テーブルを外部データ接続から直接作成しました。手動で構成したodbc接続です。
ワークブックで「すべて更新」を押すと、すべてのピボット テーブルが自動的に更新されます。
しかし今、手動の開始日と終了日でレコードセット全体を制限できるようにする必要があります...ピボットテーブルの日付フィルターを変更することは理想的ではありません.終了日の影響を受けるのは単一のフィールドだけではないため、フィールドがありますピボットの前に計算する必要があり、終了日を含む数式に依存する値を持っています。
午後に何度も Excel をクラッシュさせた後、ピボット テーブルに直接接続している場合は ? を使用できないという制限があることに気付きました。パラメータ ダイアログでセル参照を指定すると、ブックを閉じるとセル参照が失われます。
したがって、私の次のアプローチはこれを行うことでした:
Dim ReportStartDate, ReportEndDate
' Get parameters from Intro sheet
ReportStartDate = "'" & ActiveWorkbook.Worksheets("Intro").Range("$B$1").Value & "'"
ReportEndDate = "'" & ActiveWorkbook.Worksheets("Intro").Range("$B$2").Value & "'"
' There are 3 directpivot odbc connections/caches that need to be modified.
' In each query, the default report-end-date is specified by CURDATE().
' The default report-start-date is specified as '2010-01-01'
' Replace these defaults with the values retrieved above.
Dim cn As WorkbookConnection
Dim odbcCn As ODBCConnection
Dim originalsqltext, newsqltext
For Each cn In ThisWorkbook.Connections ' loop through the connections
If cn.Type = xlConnectionTypeODBC Then
Set odbcCn = cn.ODBCConnection
originalsqltext = odbcCn.CommandText
If odbcCn.Parent = "Calls" Then
newsqltext = Replace(originalsqltext, "CURDATE()", ReportEndDate)
newsqltext = Replace(newsqltext, "'2010-01-01'", ReportStartDate)
ElseIf odbcCn.Parent = "Suboutcomes" Then
newsqltext = Replace(originalsqltext, "CURDATE()", ReportEndDate)
newsqltext = Replace(newsqltext, "'2010-01-01'", ReportStartDate)
ElseIf odbcCn.Parent = "QtyCallsPerDay1" Then
newsqltext = Replace(originalsqltext, "CURDATE()", ReportEndDate)
Else
newsqltext = originalsqltext
End If
odbcCn.CommandText = newsqltext
odbcCn.Refresh
odbcCn.CommandText = originalsqltext
End If
cn.Refresh ' refresh the other connection without modification
Next
Set cn = Nothing
Set odbcCn = Nothing
しかし、odbcCn.CommandText = newsqltext 実行時エラー '1004: アプリケーション定義またはオブジェクト定義のエラーになると、エラーが発生します。これはあまり役に立ちません...
newsqltext に意図したものが含まれていることを確認しましたが、CommandText に割り当てられません。
もう 1 日グーグルで検索し、いくつかの簡単なマクロ記録実験を行った結果、CommandText を変更するには次のような構文が必要なようです。
.CommandText = Array( _
"SELECT C1.CALLID, C1.TAKENON, C1A.TAKENAT, CAST(CONCAT(DATE_FORMAT(TAKENON,'%c/%e/%y'),' ',TIME_FORMAT(TAKENAT,'%H:" _
, _
"%i:%s')) AS CHAR) AS CallDateTime, YEAR(C1.TAKENON) AS Year, CEILING(MONTH(C1.TAKENON)/3) AS Quarter, MONTH(C1.TAKE" _
, _
(巨大なので残りは省略します)...最初にマクロを記録しようとしたときに「行の継続が多すぎます」というエラーが発生したため、最初はそれが私の問題だと思ったので、クエリを短くしました可能な限り、置換前に 1428 文字に減らします。置換後、1448文字になります...しかし、コードが必要とする配列形式に解析するにはどうすればよいですか? または、これを行うためのより良い方法はありますか?
vbaで編集できるようにするためだけに、このようにクエリを台無しにしたくありません.CommandTextを変更する方法について何かが欠けているように感じます...
最初に oledb に変更しない限り odbc 接続で CommandText を変更できないというこの問題のように、私の検索で見つかったいくつかの厄介なことがありました。その後、CommandText を変更してから、接続をodbc ...しかし、それはExcel 2010より前で、これらを使用しなくなりました... http://p2p.wrox.com/excel-vba/29037-cant-set-commandtext-property-if-cache-has- 1-rpt.html
そこにリンクされている KnowledgeBase の記事http://support.microsoft.com/kb/816562は、さらに驚くべきものです... StringToArray 関数を見たときに解決策を見つけたと思いましたが、さらに読んで見ました
注: 共有ピボットキャッシュ、OLAP ベースのピボットテーブル、または複数集計範囲ベースのピボットテーブルを使用してデータベースに接続している場合、上記のコードは期待どおりに機能しない可能性があります。
その後
ワークシート上の複数のピボットテーブルが同じピボットテーブルから派生している場合、最初のピボットテーブルを処理した後、サブルーチンは機能しません。2003 年 3 月現在、この問題に対する既知の回避策はありません。
ただし、この記事は Excel 2000 ~ 2003 にのみ適用されることに注意してください。
私が試したもう1つのことは、おそらく使用できると思いましたか?パラメータを設定し、vba で設定するだけです...しかし、パラメータを使用して簡単なクエリを作成し、パラメータを新しいセル参照にポイントしている間にマクロを記録すると、マクロにはこれだけが含まれていました: Sub PARAMEDIT5() ' ' PARAMEDIT5 Macro '
'
With ActiveWorkbook.Connections("PARAMEDIT").ODBCConnection
.BackgroundQuery = False
.CommandText = Array("SELECT * FROM Calls1 where TAKENON > ?" _
)
.CommandType = xlCmdSql
.Connection = _
"ODBC;DRIVER={MySQL ODBC 5.1 Driver};UID=xxxxxxx;PWD=xxxxxxxx;SERVER=xxxxxx;PORT=3306;BIG_PACKETS=1;"
.RefreshOnFileOpen = False
.SavePassword = True
.SourceConnectionFile = ""
.SourceDataFile = ""
.ServerCredentialsMethod = xlCredentialsMethodIntegrated
.AlwaysUseConnectionFile = False
End With
With ActiveWorkbook.Connections("PARAMEDIT")
.Name = "PARAMEDIT"
.Description = ""
End With
ActiveWorkbook.Connections("PARAMEDIT").Refresh
End Sub
直接ピボット タイプの接続と、パラメーターをサポートすることがわかっている外部データ ソースに接続された通常のテーブルの両方でこれを試しました。
だから...共有ピボットキャッシュodbc接続のクエリをパラメータ化する正しい方法を知っている人はいますか?
更新:私はこれを試しました:
Dim cn, originalCn, newCn As WorkbookConnection
Dim odbcCn As ODBCConnection
Dim originalsqltext, newsqltext
Dim connStr As String
For Each cn In ThisWorkbook.Connections ' loop through the connections
If cn.Type = xlConnectionTypeODBC Then
Set odbcCn = cn.ODBCConnection
originalsqltext = odbcCn.CommandText
Set originalCn = cn
connStr = odbcCn.Connection
Select Case odbcCn.Parent
Case "Calls", "Suboutcomes"
newsqltext = Replace(originalsqltext, "CURDATE()", ReportEndDate)
newsqltext = Replace(newsqltext, "'2010-01-01'", ReportStartDate)
Case "QtyCallsPerDay1"
newsqltext = Replace(originalsqltext, "CURDATE()", ReportEndDate)
Case Else
newsqltext = originalsqltext
End Select
Set newCn = ActiveWorkbook.Connections.Add(odbcCn.Parent & "New", "WhoCares", connStr, newsqltext)
Set cn = newCn
cn.Refresh
Set cn = originalCn
newCn.Delete
Else
cn.Refresh ' refresh any other connections without modification
End If
Next
Set cn = Nothing
Set odbcCn = Nothing
Set newCn = Nothing
Set originalCn = Nothing
そして、コマンドテキストを必要なものにするという点で、私が望むことをしているように見えますが、ステップスルーしても cn.Refresh は何もしません。更新されていても、ピボットが更新されていない場合、Calls1 を探している場所を確認でき、更新が発生した瞬間に Calls1New という名前が付けられていますが、接続は何もしていません (クエリは通常、完了するまでに数分かかります)。それとも、同じ名前の既存の接続に割り当てることができないのでしょうか? cn = newCn を設定すると、どちらも同じ名前でまったく同じに見えます。
もう少し調べてみますが、他の誰かがこのようなことをしたことがあれば、もっと助けていただければ幸いです. あなたがこれまでに与えてくれたものに感謝します!
編集:だから私は元に戻っています
odbcCn.CommandText = newsqltext
cn.Refresh
odbcCn.CommandText = originalsqltext
http://support.microsoft.com/kb/816562で見つけた odbcCn.CommandText = StringToArray(newsqltext) cn.Refresh odbcCn.CommandText = StringToArray(originalsqltext) も試しました。どちらも機能しませんでした。
エラーの直前にあるので、originalsqltext と newsql text を投稿します。newsqltext と同様に、元の sqltext をクエリのダイアログ ボックスに手動で貼り付けると、元のsqltext が正常に機能することに注意してください。
**新しい情報のため、以前の編集を削除しました**
注 -同様の問題のように思われるスレッドExcel VBA: Update Pivot Sourcedataを見つけました。ただし、このスレッドは2009年のものなので、Excel 2010を使用していない可能性が高いです。
For Each pvtC In ThisWorkbook.PivotCaches
name = pvtC.WorkbookConnection.name
originalsqltext = pvtC.CommandText
pvtC.CommandText = originalsqltext
Next
pvtC.CommandText = originalsqltextでも失敗します
更新: これはクエリ自体とは何の関係もありませんが、複数のピボット テーブルが同じピボットキャッシュを指しているという条件であると確信しています。簡単なクエリで新しい外部データソースを作成しました
SELECT * FROM clientdashboard1.Calls1 WHERE TAKENON BETWEEN '2010-01-01' AND CURDATE()
そのクエリとして。接続に AlphaTest という名前を付け、そこからピボット テーブルを作成し、そのピボット テーブルを別のシートにコピーして、別のフィールドを使用しました。最初にこれを実行するようにコードを変更しました。
For Each pvtC In ThisWorkbook.PivotCaches
name = pvtC.WorkbookConnection.name
If name = "AlphaTest" Then
originalsqltext = pvtC.CommandText
pvtC.CommandText = originalsqltext
End If
Next
まったく同じ時点で失敗しました pvtC.CommandText = originalsqltext
次に、2 番目のピボット テーブルを削除し、もう一度実行したところ、機能しました。
次に、念のため、元の巨大なクエリを挿入して、もう一度実行しました。出来た。ただし、別のしわが明らかになりました...コードを介して CommandText を変更すると、更新されます。したがって、置換を行い、更新を行ってから元に戻すという私の最初の計画は、2番目の割り当てでテーブルが再び更新されるため、機能しません(機能した場合)。
アップデートこれはますます良くなっています。おそらく1つのレコードだけで、ピボットキャッシュのダミーコピーを作成することについて考えました1。レポート タスクを実行します (シートをコピーし、リンクを解除し、名前を付けて保存し、閉じるのが通常の方法です)。次に、元のブックに戻り、すべてのピボット テーブルをそれぞれのダミー キャッシュにポイントします。さて、私が持っていた AlphaTest データソースを知っていますか? pvtC.CommandText = originalsqltext が実際にクエリを変更し、AlphaTest を更新させたと思いました...ああ、私の友人。これは、AlphaTest のコピーである Connection と呼ばれる新しい接続を作成しました。いいよ。これをどのように使用できますか?..... 試してみたいアイデアがいくつかありますが、他の誰かがこれに対処した場合は、