COM上でRangeをCellsで使うには。 – プログラミング – Home

COM上でRangeをCellsで使う...
 
通知
すべてクリア

[解決済] COM上でRangeをCellsで使うには。


初心者
 初心者
(@初心者)
ゲスト
結合: 24年前
投稿: 206
Topic starter  

前回質問させて頂いて、解決させていただいたものです。その時はありがとうございま
した。

環境:VC++2008EE Windows vist,-7にてCOMにてExcelを使うソフトを作ってい
ます。(Excelをデータベースとして利用)

(以下のpWorksheetや、pRangeはIDispatchです。)
大体できたのですが、改良を加えて(加えさせられて)います。
Excelシートを読むときの範囲指定にpWorksheet, LRangeとして var.vt=VT_BSTR;
var.bstrVal=A20:c30としていますが、これをVBAでいう、Range(Cells(i,j).Address
():Cells(k,l).Address())のようにするか、もしくは、直接Cellsを使って範囲指定した
いのですが、どなたかご存知の方教えてください。
ちなみにpWorksheet, LCellsとしてvar.vt=VT_BSTR; var.bstrVal=20,1
にてpRangeを取得した(間違い?)と思って、pRange、LResizeを実行するとえらーに
なります。どうしてもRangeとCellsが関連付けできません。教えてください。


引用未解決
トピックタグ
初心者
 初心者
(@初心者)
ゲスト
結合: 24年前
投稿: 206
Topic starter  

方法は見つかりました。

以下は、Range(Cells(10,8).Address():Cells(20,20).Address())
[ Range(H10:j20) ]の例です。
IDispatch *pWoksheetでLCellsをvar.bstrVal = L0,8にてInvoke一回実施。
これでC(カラム)方向がIDispatchにて還ります。(H=8が還る。)
これを例えば、IDispatch *pArea = varResult.pdispValとします。

そしてpAreaにて再度LCellsをvar.bstrVal = L0,10にてInvoke実施するとR(row)方
向が還り、Cells(10,8)が作成されます。

pAreaをLAddressにてInvoke実施すると、varResult.bstrValに$H$10が還ってきてま
す。

次は次の20:20ですが、同じことを繰り返すと、varResult.bstrValに$J$20が還って
きてます。

これを文字列の結合で$H$10:$j$20を作成してRangeのvar.bstrVal=エリア
とすれば、うまくいくのですが・・・・・・

もっと簡単な方法があるような気がして・・・・
どなたかご存じなしでしょうか。


返信引用
蒼の洞窟
 蒼の洞窟
(@蒼の洞窟)
ゲスト
結合: 12年前
投稿: 28
 

Cellsで一発で目的のアドレスのRangeをとるには
引数として、列番号と行番号を渡す必要があります。

>>Range(Cells(i,j).Address():Cells(k,l).Address())
なら、Resizeプロパティを使ったほうが楽かもしれません。

列数をi→k、行数をj→lにするので単純に引き算した値をRisizeに渡せばいいです。

VARIANT varIndex[2];
VariantInit(&varIndex[0]);
varIndex[0].vt = VT_I4;
varIndex[0].lVal = 1; // 列番号
VariantInit(&varIndex[1]);
varIndex[1].vt = VT_I4;
varIndex[1].lVal = 1; // 行番号
VariantInit(&varResult);
Invoke(pWorksheet, LCells, DISPATCH_PROPERTYGET, varIndex, 2, &varResult);
pRange = varResult.pdispVal;

VariantInit(&varResult);
Invoke(pRange, LAddress, DISPATCH_PROPERTYGET, NULL, 0, &varResult);
BSTR bstrAddress = SysAllocString(varResult.bstrVal);

// bstrAddress : $A$1

SysFreeString(bstrAddress);

VARIANT varSize[2];
VariantInit(&varSize[0]);
varSize[0].vt = VT_I4;
varSize[0].lVal = 5; // 5列増やす→A,B,C,D,E
VariantInit(&varSize[1]);
varSize[1].vt = VT_I4;
varSize[1].lVal = 3; // 3行増やす→1,2,3
VariantInit(&varResult);
Invoke(pRange, LResize, DISPATCH_PROPERTYGET, varSize, 2, &varResult);
IDispatch* pRange2 = varResult.pdispVal;

VariantInit(&varResult);
Invoke(pRange2, LAddress, DISPATCH_PROPERTYGET, NULL, 0, &varResult);
bstrAddress = SysAllocString(varResult.bstrVal);

// bstrAddress : $A$1:$E$3

SysFreeString(bstrAddress);

pRange2->Release();


返信引用
初心者
 初心者
(@初心者)
ゲスト
結合: 24年前
投稿: 206
Topic starter  

蒼の洞窟さん、今回もありがとうございます。今日は時間がないので、今夜試してみます

教えていただいた、オブジェクトブラウザやOleView.exeにておおよその方向性がわかる
ようになりました。ただ、戻り値がわからないので試行錯誤の連続です。

ところで、この前のHyperlinksのことで、もう少し教えてください。このまえのだと、
Rangeの範囲でリンクのみをまとめたリストで帰ってくるのですが、、リンクがないセル
はNULLなどでリストを埋めたリスト、つまりRangeの行数と戻りのリストが同じ数
といったようなことはできないのでしょうか。
すみません、甘えた質問で・・・


返信引用
蒼の洞窟
 蒼の洞窟
(@蒼の洞窟)
ゲスト
結合: 12年前
投稿: 28
 

そんな便利な関数はないので自作してください。
HyperlinkオブジェクトからRangeオブジェクトがとれるのでそこから
ColumnプロパティとRowプロパティでセルの位置がわかります。

Rangeオブジェクトを1セルずつループしてHyperlinks→Hyperlinkと取得したほうが
やりやすいかもね。

というか、左上のセルとその横何列、下何行ってわかっていれば、Offset使って
ループしたほうがいいかな。


返信引用
初心者
 初心者
(@初心者)
ゲスト
結合: 24年前
投稿: 206
Topic starter  

蒼の洞窟さん、いつも親切な回答ありがとうございます。
本当に感謝いたします。

①:RangeとCellsの件
最初の私の考え方(sheet→Cells→Renge→Resize)があっていたことにびっくりやら、方
向性が間違っていなかったこと安心やら、まあ、驚きました。蒼の洞窟さんに教えてい
ただいた、オブジェクトブラウザやOleView.exeのおかげです。(i,j)の情報入力の方法
が間違っていたのですね。この記入方法はSAFEARRAYへのアクセス方法に似ているな~~
と思いました。(COMっていうかInvoke関係の手法なんでしょうか・・・)

②:Hyperlinksの件
甘えた質問にも親切な回答、大変ありがとうございます。
私もSAFEARRAY的な挑戦(試行錯誤)をしてみましたが、全てエラーで・・・・
今は、Rangeオブジェクトを1セルずつループにてListViewに落としています。
教えていただいた、『HyperlinkオブジェクトからRangeオブジェクト・・・』や
『Offset』を試してみて今のソフトにあったものを見つけます。

本当にありがとうございました。(御礼!)


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました