フォーラム


ゲスト  

ようこそ ゲスト さん。このフォーラムに投稿するには 登録が必要です。

ページ: 1 2 3 [4]
トピック: Delphi Advent Calendar 2013
DEKO
管理者
投稿数: 2649
12/19 Delphi の Interface
on: 2013/12/19 00:39 Thu

[Delphi の Interface]
http://delphimaniacs.blogspot.com/2013/12/delphi-interface.html

DEKO
管理者
投稿数: 2649
12/20 コンポーネントの名前の付け方について
on: 2013/12/20 12:48 Fri

[コンポーネントの名前の付け方について]
http://qiita.com/sevenOfNine/items/4b43a0d1f1bec3b98fbb

DEKO
管理者
投稿数: 2649
12/21 Nixie(ニキシ管) 風 コンポーネントの作成
on: 2013/12/21 05:21 Sat

[Nixie(ニキシ管) 風 コンポーネントの作成]
http://i65000.blogspot.jp/2013/12/nixie.html

DEKO
管理者
投稿数: 2649
12/22 FireMonkey で閉じるボタン付きの TabItem を作る
on: 2013/12/22 00:17 Sun

[FireMonkey で閉じるボタン付きの TabItem を作る]
http://delphimaniacs.blogspot.jp/2013/12/firemonkey-tabitem.html

DEKO
管理者
投稿数: 2649
12/23 FireMonkey の TWebBrowser を Win/Mac で使えるようにする!
on: 2013/12/23 07:25 Mon

[FireMonkey の TWebBrowser を Win/Mac で使えるようにする!]
http://delphimaniacs.blogspot.jp/2013/12/firemonkey-twebbrowser-winmac.html

DEKO
管理者
投稿数: 2649
12/24 演算ワークの話...!?
on: 2013/12/23 23:59 Mon

{ これは Delphi Advent Calendar 2013 の 12/24 分の記事です }

前回はコンポーネントエディタの作り方をやりました…それは TStringGrid 用のコンポーネントエディタだったのですが、「TStringGrid と言えば使っていて思う事が…」今回はそんな話です (多分)。

TStringGrid は基本的に表示用です…もちろん表計算のように入力する事もありますね。表計算のように入力できちゃうと、"計算させる" という要望が当たり前のように出てきますね。そこで思うことは…

  • TStringGrid は文字列しか格納できない。
  • Objects[] があるのはもちろん解ってる。
  • 計算とかどうするの?毎回 StrToFloat() / FloatToStr() とかして書き戻してるの?

という事です。「表が固定」 あるいは 「読み込んだ後は変化しない」 というのなら、Currency の二次元配列とか、二次元動的配列とかで TStringGrid と同じサイズのワークを作ってそちらで計算してやればいいと思うのです…これは多分普通に辿り着く考え方だと思います。

[配列型 (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/XE5/ja/%E6%A7%8B%E9%80%A0%E5%8C%96%E5%9E%8B#.E9.85.8D.E5.88.97.E5.9E.8B

…でもね。実際にはとんでもない要求があって、縦横 (Row/Col) が条件によって可変しちゃったり、グリッド上には存在しないデータを元に計算しなくちゃいけない事もありますよね?ぇ、そんなのなかったですか?それはとても幸せなことです (^^;A

で、作ったのがコレです (ここに貼るにはリストがちょっと長いので定義部だけ)。

[uExtendedSheet.pas]
type
TExtendedDynArray = array of Extended;
{$EXTERNALSYM TExtendedDynArray 'System::TExtendedDynArray'}
TExtended2DDynArray = array of TExtendedDynArray;

TExtendedSheet = packed record
Value: TExtended2DDynArray; // データ実体
private
{ Access Methods (for Property) }
function GetCells(ACol, ARow: Integer): Extended;
procedure SetCells(ACol, ARow: Integer; const Value: Extended);
function GetColCount: Integer;
procedure SetColCount(const Value: Integer);
function GetRowCount: Integer;
procedure SetRowCount(const Value: Integer);
{ Private Methods }
function GetValidCol(aCol: Integer): Integer; // 有効な列インデックスを返す
function GetValidRow(aRow: Integer): Integer; // 有効な行インデックスを返す
public
{ Methods }
procedure AddCol; // 列を追加
procedure AddRow; // 行を追加
procedure Clear; // すべての値を 0 クリアする
procedure ClearCol(aCol: Integer); // 指定された列を 0 クリア
procedure ClearRow(aRow: Integer); // 指定された列を 0 クリア
procedure DeleteCol(aCol: Integer); // 指定された列を削除
procedure DeleteRow(aRow: Integer); // 指定された行を削除
procedure Init(Cols, Rows: Integer); // 配列のサイズを初期化する
procedure InsertCol(aCol: Integer); // 指定された位置に列を挿入
procedure InsertRow(aRow: Integer); // 指定された位置に行を挿入
function MaxValue(aCol: Integer): Extended; // MaxValue(): 最大値を返す
function Mean(aCol: Integer): Extended; // Mean(): 平均を返す
procedure MeanAndStdDev(aCol: Integer; var Mean, StdDev: Extended); // MeanAndStdDev(): 平均と標準偏差を返す
function MinValue(aCol: Integer): Extended; // MinValue(): 最小値を返す
function PopnStdDev(aCol: Integer): Extended; // PopnStdDev() : 母標準偏差を返す
function PopnVariance(aCol: Integer): Extended; // PopnVariance(): 母分散を返す
procedure SetColValues(aCol: Integer; aValues: array of Extended); // 列データをセット
procedure SetRowValues(aRow: Integer; aValues: array of Extended); // 行データをセット
function StdDev(aCol: Integer): Extended; // StdDev(): 標準偏差を返す
function Sum(aCol: Integer): Extended; // Sum(): 合計値を返す
function SumOfSquares(aCol: Integer): Extended; // SumOfSquares() : 2 乗和を返す
procedure SumsAndSquares(aCol: Integer; var Sum, SumOfSquares: Extended); // SumsAndSquares() : 合計値と 2 乗和を返す
function TotalVariance(aCol: Integer): Extended; // TotalVariance(): 全分散を返す
function Variance(aCol: Integer): Extended; // Variance(): (標本)分散を返す
{ Properties }
property Cells[ACol, ARow: Integer]: Extended read GetCells write SetCells; // セル
property ColCount: Integer read GetColCount write SetColCount; // 列の数
property RowCount: Integer read GetRowCount write SetRowCount; // 行の数
end;

  
ミもフタもない言い方をすれば "Extended 型二次元動的配列の高度なレコード型" という事になります。TStringGrid のメソッドやプロパティのような感じで使えます。TStringGrid 用計算ワークというより汎用計算ワークですね。名前を TExtendedMatrix にしようかと思ったのですが、行列計算用という訳ではないので Matrix という名前は避けました。演算子オーバーロードを実装すれば行列計算用途に使えるようにする事もできますけどね (串刺し演算用にもできますが)。

[高度なレコード型 (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/ja/%E6%A7%8B%E9%80%A0%E5%8C%96%E5%9E%8B#.E3.83.AC.E3.82.B3.E3.83.BC.E3.83.89.E5.9E.8B.EF.BC.88.E9.AB.98.E5.BA.A6.EF.BC.89

[演算子のオーバーロード(Delphi) (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/ja/%E6%BC%94%E7%AE%97%E5%AD%90%E3%81%AE%E3%82%AA%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AD%E3%83%BC%E3%83%89%EF%BC%88Delphi%EF%BC%89

さて、前置きはここまでにして具体的な使い方を。

uses
..., uExtendedSheet;

procedure TForm1.Button1Click(Sender: TObject);
var
Sheet: TExtendedSheet;
begin
with Sheet do
begin
// 動的配列を初期化
Init(3, 3);
Clear;

// 三行のデータをセット
Cells[0, 0] := 1;
Cells[1, 0] := 2;
Cells[2, 0] := 3;

Cells[0, 1] := 4;
Cells[1, 1] := 5;
Cells[2, 1] := 6;

Cells[0, 2] := 7;
Cells[1, 2] := 8;
Cells[2, 2] := 9;

// 一列目の値の最大値を表示
ShowMessage(FloatToStr(MaxValue(0)));

// 二列目の値の合計値を表示
ShowMessage(FloatToStr(Sum(1)));

// 三列目の値の平均値を表示
ShowMessage(FloatToStr(Mean(2)));
end;
end;

 
配列用関数である Sum() や Mean() 等もメソッドとして実装してありますので簡単な計算ならこなせます。複雑なものはループでグルグルするしかないですけれど、StrToFloat() / FloatToStr() とかで何度も何度も書き戻すよりかは遥かにスマートに書けます。

ShowMessage() のトコですが、XE3 以降だとプリミティブ型にヘルパーがあり、XE4 以降だと…

      // 一列目の値の最大値を表示
ShowMessage(MaxValue(0).ToString(ffGeneral, 10, 2)); // XE4 or later

// 二列目の値の合計値を表示
ShowMessage(Sum(1).ToString(ffGeneral, 10, 2)); // XE4 or later

// 三列目の値の平均値を表示
ShowMessage(Mean(2).ToString(ffGeneral, 10, 2)); // XE4 or later

 
ToString() を用いてこのように書けます。コードエディタの補完が利くので便利ですね。ToString() は Extended 型のヘルパー (TExtendedHelper) のメソッドですが、残念ながら XE3 にはありません。

[System.SysUtils.TExtendedHelper (DocWiki)]
http://docwiki.embarcadero.com/Libraries/ja/System.SysUtils.TExtendedHelper

動的配列のリサイズは RowCount / ColCount プロパティで行え、AddCol() / AddRow() / InsertCol() / InsertRow() / DeleteCol() / DeleteRow() メソッドで任意の列と行を追加 (or 挿入) したり削除したりできます。拡張方向にリサイズした場合、拡張した領域は 0 で初期化されます。

動的配列へのアクセスは Cells[] プロパティで行えます。TStringGrid みたいですね…ただ、一件一件値をセットするのは面倒なので、一気にデータを登録する SetRowValues() / SetColValues() も実装してあります。使い方はこんな感じです。

      // 三行のデータをセット
SetRowValues(0, [1, 2, 3]);
SetRowValues(1, [4, 5, 6]);
SetRowValues(2, [7, 8, 9]);

 
SetRowValues() の第一引数は "行インデックス" で、第二引数は Extended 型のオープン配列パラメータです。基本的にオープン配列パラメータのパラメータ数は ColCount と一致させなくてはいけませんが、後方を省略する事も可能です。省略部分の値は更新されません (0 クリアされる訳ではありません)。例えば列数が 3 の場合、以下のコードを実行した後の Value[0] の値は (0, 0, 3) となります。

  Sheet.SetRowValues(0, [1, 2, 3]);
Sheet.SetRowValues(0, [0, 0]);

 
逆に、オープン配列パラメータのパラメータ数が ColCount より大きい場合には超過分は無視されます。エラーにはなりません。

「オープン配列パラメータって何ぞ?」という方もいらっしゃるかもしれませんので、一応説明しておきます。オープン配列パラメータで一番よく目にするのは Format() 関数でしょう。Format() 関数の第二引数はオープン配列パラメータとなっています (正確には "型可変オープン配列パラメータ" です)。

[System.SysUtils.Format (DocWiki)]
http://docwiki.embarcadero.com/Libraries/ja/System.SysUtils.Format

SetRowValues() の定義は以下のようになっています。

procedure SetRowValues(aRow: Integer; aValues: array of Extended);

 
仮引数に "array of 型" を使った場合、それはオープン配列パラメータとなります。このようにして Extended の配列を渡す事もできます。

procedure TForm1.Button2Click(Sender: TObject);
var
RowVal: array [0..2] of Extended;
begin
RowVal[0] := 100;
RowVal[1] := 200;
RowVal[2] := 300;
Sheet.SetRowValues(0, RowVal);
end;

 
オープン配列パラメータに引数として渡せるのは以下のものです。

  • 指定した型の静的配列
  • 指定した型の動的配列
  • オープン配列コンストラクタ

"オープン配列コンストラクタ" というのは[]で括ったアレです。似ていますが集合 (Set of) ではありません。今回、二次元動的配列でオープン配列パラメータの話をしているのでややこしいのですが、配列とオープン配列パラメータに直接の関係はありません。

[集合 (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/ja/%E6%A7%8B%E9%80%A0%E5%8C%96%E5%9E%8B#.E9.9B.86.E5.90.88

パラメータにはちょっと特殊な「(オープン)配列パラメータ」というのがあって、この特殊なパラメータの場合には「(オープン)配列コンストラクタ」と呼ばれる機構を使い「配列パラメータを直接作って渡す事ができる」という事になります。この記述方法は "型の配列ではなくパラメータの配列である" というのがミソです。それ故、以下のようなコードは書けません。

procedure foo(Values: array of array of Integer);
begin

end;

 
裏を返せば Format() 関数の第二引数は型可変オープン配列パラメータなのですから、以下のようなコードが通ります。

procedure TForm1.Button1Click(Sender: TObject);
var
VarRec: array [0..1] of TVarRec;
begin
// Parameter #1
VarRec[0].VType := vtInteger;
VarRec[0].VInteger := 100;
// Parameter #2
VarRec[1].VType := vtUnicodeString;
VarRec[1].VUnicodeString := PChar('ABC');
// Format()
ShowMessage(Format('%d %s', VarRec));
end;

 
型可変オープン配列パラメータは "型が TVarRec なオープン配列パラメータ" と同義です。

[配列パラメータ (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/ja/パラメータ#.E9.85.8D.E5.88.97.E3.83.91.E3.83.A9.E3.83.A1.E3.83.BC.E3.82.BF

[System.TVarRec (DocWiki)]
http://docwiki.embarcadero.com/Libraries/ja/System.TVarRec

ちょっと話が逸れてしまったので動的配列の話に戻りましょう。通常、動的配列の配列確保には SetLength() を使います。で、二次元動的配列の場合には SetLength() して確保した動的配列を要素毎にさらに SetLength() します。

procedure TForm1.Button1Click(Sender: TObject);
var
Str2DDynArray: array of array of String;
Col: Integer;
begin
// 一次元目の確保
SetLength(Str2DDynArray, 10);
// 二次元目の確保
for Col:=Low(Str2DDynArray) to High(Str2DDynArray) do
SetLength(Str2DDynArray[Col], 10);
end;

 
こんな感じに。二次元目の確保でグルグルしなきゃいけない理由はヘルプに書いてあります。

特定の次元の配列の長さがすべて同じではない多次元動的配列を作成することもできます。

 
[多次元動的配列 (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/ja/%E6%A7%8B%E9%80%A0%E5%8C%96%E5%9E%8B#.E5.A4.9A.E6.AC.A1.E5.85.83.E5.8B.95.E7.9A.84.E9.85.8D.E5.88.97

碁盤状でない二次元動的配列 (ジャグ配列) を作るためですね。表計算のような碁盤状の二次元動的配列 (矩形配列) の確保のためには DynArraySetLength() という関数が別にあります。

[System.DynArraySetLength (DocWiki)]
http://docwiki.embarcadero.com/Libraries/ja/System.DynArraySetLength

…ですが、そこにも書いてあるように SetLength() は多次元動的配列を一度で確保できるのです。

同じ操作を SetLength 手続きを使って行うこともできます(この方法が推奨されています)。

begin
 SetLength(A, 3, 4);
end.

 
[多次元配列の初期化。(全力わはー)]
http://d.hatena.ne.jp/tales/20090816/1250416430

「だったら、SetLength() の方に書いておいてくれよ!」と思うのは私だけでしょうか (^^;A

[System.SetLength (DocWiki)]
http://docwiki.embarcadero.com/Libraries/ja/System.SetLength

ちなみにこの SetLength() の書き方ですが、Delphi 4 から利用可能です(Delphi XE4 からではありません。Delphi 4 の発売は 1998 年ですから…15年前からですね)。

そりゃそうなのですが、動的配列をラッピングするという考え方は以前からあるようで、Delphi Q&A の投稿にも以下のようなものがありました。

[TListでの二次元配列クラスの作成 (Delphi Q&A)]
http://homepage1.nifty.com/MADIA/delphi/delphi_bbs/200405/200405_04050048.html

この中で "ポインタの二次元配列の代わりに pf32bit な TBitmap を使う" というアイデアがレスされていました。(64bit アプリを考えると)今となっては使えないテクニックではありますがとてもユニークですよね。その昔の 8bit /16bit 機では使えるメモリが少なかったので VRAM をメモリとして使っていたのを思い出しました。

メモリが少ない…
リニアにメモリが使えない…
16bit 機にはセグメントが (EMS ってダイエット器具じゃないんやで) …
X68Kとかはメモリをリニアに使えましたけどね (それでも最大 12MB)…
マシン性能も今から考えれば 1/100 以下だしなぁ…
スミマセン…オッサンの昔話です (w

 
さてさて、今回の記事はここまでとなります。TExtendedSheet は演算ワークとしての基本はそれなりに押さえてあると思いますが、好きなように改変してお使いください。Excel っぽい事をやりたいのであれば、データとして何でも放り込める TVarRec の動的二次元動的配列で作ってみるのも面白いかと思います。面白い機能を持つ演算ワークができたり、「いや、演算用ワークならもっといい手法があるよ!」的なのがあったら是非教えてください♪

この記事で紹介した uExtendedSheet のアーカイブは以下にあります。

Download: http://ht-deko.minim.ne.jp/software/uextendedsheet_110.zip

※このユニットはハラヘッタウェアとなっています。
http://ht-deko.minim.ne.jp/delphiforum/harahettaware/

DEKO
管理者
投稿数: 2649
12/25 チラ裏(個人的な事を振り返る)
on: 2013/12/25 04:47 Wed

[チラ裏(個人的な事を振り返る)]
http://delphimaniacs.blogspot.jp/2013/12/blog-post.html

DEKO
管理者
投稿数: 2649
Re: 12/24 「魚雷跳び」について
on: 2013/12/25 05:57 Wed

それは細川さんが twitter でハードルを上げた事から始まった。
https://twitter.com/pik/status/414424995830329344

@pik 「お疲れしたー (実は 12/24 分がまだ終わっていない…てか、始まってもいねーよというのはナイショだ)」#delphiadvent2013

@ht_deko スゴいのが書かれるって事を知っているので、触れませんでした!

@pik ((((;゚Д゚)))) ハ、ハードルを上げやがった!! #delphiadvent2013 #delphi_jp

@ht_deko ドュフフ…

 
「コンチクショウ…」…orz

ここで僕はどうやったらこのハードルを越えられるのかを考えた。しかし、革新的なネタなど持ち合わせてはいないし、たとえあったとしてもこの短期間で記事にするのは不可能に思えた。ハードルを越える方法は 2 つある。

  • 技術的にスゴい記事を書く
  • ネタ的にスゴい記事を書く

…イロイロ思案してみるも、後者しか残された方法はないとの結論に至った。

「ネタを仕込むとするか…」

12/24 の記事という事なので "くだらないネタ" はすぐに考え付いた。あとはこれにどうやって至らせるか、だ。流れが不自然だとネタを一発で看破されてしまう…それでは面白くない。試行錯誤を繰り返し、話題をちょっとずつズラしながら文章をもっともらしくくっつけたものが 12/24 のアドベントカレンダーの記事となった。つまり、あの記事は最後のネタから冒頭の TStringGrid までを逆に辿って書かれている。

うん。努力した割には面白くないオチが待っているんだよ。オチが分からない?最後の囲みの「メモリが少ない…」から縦に読んでみようか…うんまぁ、そういう事だね。メリークリスマス!

See Also:

[魚雷跳び (ニコニコ動画)]
http://www.nicovideo.jp/watch/sm15323247

DEKO
管理者
投稿数: 2649
Re: 12/24 演算ワークのワークについて
on: 2013/12/28 09:06 Sat

TExtendedSheet は TStringGrid のワークとして使うには便利です。

var
Sheet: TExtendedSheet;

...

procedure TForm1.DynToGrid;
var
i,l: Integer;
begin
StringGrid1.ColCount := Sheet.ColCount;
StringGrid1.RowCount := Sheet.RowCount;
for l:=0 to Sheet.RowCount-1 do
for i:=0 to Sheet.ColCount-1 do
StringGrid1.Cells[i,l] := FloatToStr(Sheet.Cells[i,l]);
end;

 
演算結果はこのようにして StringGrid に返す事ができます。TStringGrid を使わない内部ワークだったとしても、確認用に TStringGrid を貼り付けて表示させる事ができます。

…さて。

動的配列の仕様を理解しているヒトにはコレでもいいのですが、うろ覚えの方が TExtendedSheet をワークのワークとして使おうとすると頭を抱える事になってしまうでしょう。現象を説明するために、まずは静的な二次元配列で確認してみます。

var
E1, E2: array [0..2, 0..2] of Extended;
begin
// E1 に値をセット
E1[0][0] := 1;
E1[0][1] := 2;
E1[0][2] := 3;
E1[1][0] := 4;
E1[1][1] := 5;
E1[1][2] := 6;
E1[2][0] := 7;
E1[2][1] := 8;
E1[2][2] := 9;
// E2 へコピー
E2 := E1;
// E2 に値をセット
E2[0][0] := 10;
E2[0][1] := 10;
E2[0][2] := 10;
// 表示
ShowMessage(CurrToStr(E1[0][0])); // 1
ShowMessage(CurrToStr(E2[0][0])); // 10
end;

 
これを動的配列に変更してみます。

var
E1, E2: array of array of Extended;
begin
// 配列を確保
SetLength(E1, 3 ,3);
// E1 に値をセット
E1[0][0] := 1;
E1[0][1] := 2;
E1[0][2] := 3;
E1[1][0] := 4;
E1[1][1] := 5;
E1[1][2] := 6;
E1[2][0] := 7;
E1[2][1] := 8;
E1[2][2] := 9;
// E2 へコピー (?)
E2 := E1;
// E2 に値をセット
E2[0][0] := 10;
E2[0][1] := 10;
E2[0][2] := 10;
// 表示
ShowMessage(CurrToStr(E1[0][0])); // 1 (?)
ShowMessage(CurrToStr(E2[0][0])); // 10
end;

 
いかがだったでしょうか?何故このような事になるのかは以下のリンクを参照してください。

[動的配列 (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/ja/%E6%A7%8B%E9%80%A0%E5%8C%96%E5%9E%8B#.E5.8B.95.E7.9A.84.E9.85.8D.E5.88.97

[Delphi/動的配列の罠 (TOBY SOFT wiki)]
http://tobysoft.net/wiki/index.php?Delphi%2F%C6%B0%C5%AA%C7%DB%CE%F3%A4%CE%E6%AB

「知ってるよ!Copy() 使えばいいんでしょ?」…果たしてそうでしょうかね?

var
E1, E2: array of array of Extended;
begin
// 配列を確保
SetLength(E1, 3 ,3);
// E1 に値をセット
E1[0][0] := 1;
E1[0][1] := 2;
E1[0][2] := 3;
E1[1][0] := 4;
E1[1][1] := 5;
E1[1][2] := 6;
E1[2][0] := 7;
E1[2][1] := 8;
E1[2][2] := 9;
// E2 へコピー (?)
E2 := Copy(E1, 0, Length(E1)); // Copy() に変えてみた!
// E2 に値をセット
E2[0][0] := 10;
E2[0][1] := 10;
E2[0][2] := 10;
// 表示
ShowMessage(CurrToStr(E1[0][0])); // 1 (?)
ShowMessage(CurrToStr(E2[0][0])); // 10
end;

 
結果は変わりませんでしたね。二次元動的配列の場合、正しくはこうなります。

  // E2 へコピー
SetLength(E2, Length(E1));
for i:=Low(E1) to High(E1) do
E2[i] := Copy(E1[i], 0, Length(E1[i]));

 
これを毎回毎回記述するのも面倒ですし、動的配列の仕様を理解していても代入でケアレスミスしやすいので、TExtendedSheet に Assign() メソッドと Cols[] / Rows[] プロパティを追加しておきました。Assign() の使い方は次の通りです。

var
E1, E2: TExtendedSheet;
i: Integer;
begin
// 配列を確保
E1.Init(3, 3);
// E1 に値をセット
E1.SetRowValues(0, [1, 2, 3]);
E1.SetRowValues(1, [4, 5, 6]);
E1.SetRowValues(2, [7, 8, 9]);
// E2 へコピー (E2 := E1; はダメ)
E1.Assign(E2);
// E2 に値をセット
E2.SetRowValues(0, [10, 10, 10]);
// 表示
ShowMessage(CurrToStr(E1.Cells[0, 0])); // 1
ShowMessage(CurrToStr(E2.Cells[0, 0])); // 10
end;

 
Cols[] / Rows[] の使い方は次の通りです。

var
ES: TExtendedSheet;
EA: TExtendedDynArray;
i: Integer;
begin
// 配列を確保
ES.Init(3, 3);
// ES に値をセット
ES.SetRowValues(0, [1, 2, 3]);
ES.SetRowValues(1, [4, 5, 6]);
ES.SetRowValues(2, [7, 8, 9]);
// EA へ 1 行目をコピー
EA := ES.Rows[0];
// EA[0] の値を書き換え
EA[0] := 10;
EA[1] := 10;
EA[2] := 10;
// ES の 2 行目にコピー
ES.Rows[1] := EA;
// 表示
ShowMessage(CurrToStr(ES.Cells[0, 0])); // 1
ShowMessage(CurrToStr(ES.Cells[0, 1])); // 10
end;

 
Cols[] / Rows[] は右辺にある場合、左辺の TExtendedDynArray を事前に初期化 (あるいは SetLength) しておく必要はありません。

ダウンロード:
http://ht-deko.minim.ne.jp/software/uextendedsheet_110.zip

ページ: 1 2 3 [4]
WP Forum Server by ForumPress | LucidCrew
バージョン: 1.7.5 ; ページロード: 0.083 sec.