Script談話室バックナンバー2005

パス図形に沿って、文字を均等配列にする   与太郎さんた
email:  Wed Dec 22 18:21:56 2004

ちょっと早いクリスマスプレゼントです。
標準の2Dパステキストは曲線上に文字を配置出来ないので,スクリプトを書いてみました。
アクティブレイヤの文字とパス図形を選択して実行します。

パス図形は、多角形に変換できる図形なら何でも構いません。(渦巻き図形もグループ解除す
れば可能です。)

VW11ではDoMenuTextByNameが正常に動作しないので、113〜116行をコメントアウトして、117
行を有効にしてください。

procedure AlignTextOnCurve;
{ パス図形に沿って、文字を均等配列にする(VW8.5〜10.5) }
{ VW11では、113〜116行をコメントアウトして、117行を有効にする }
{ アクティブレイヤの文字とパス図形を選択して実行 }
{$ DEBUG}
const
_MaxIndex = 254;
_LineObj = 2;
_RectObj = 3;
_OvalObj = 4;
_PolyObj = 5;
_ArcObj = 6;
_RRectObj = 13;
_CurveObj = 21;
_TextObj = 10;
_LF = Chr(13);
_
var
_hT, hP, hG_:handle;
_str_:string;
_ch_num_:integer;
_txt_color_:integer;
_txt_vAlign_:integer;
_ch_numByte, ch_font, ch_size, ch_style_:array[0..MaxIndex] of integer;
_ch_dist, ch_wd, ch_x, ch_y, ch_ang_:array[0..MaxIndex] of real;
_ch_chars_:array[0..MaxIndex, 1..2] of char;
_ch_isSpace_:array[0..MaxIndex] of boolean;
_ch_hnd_:array[0..MaxIndex] of handle;
_pathLen_:real;
_spc_:real;
_
function Closed(hPoly: handle): boolean;
{多角形が閉じていればTRUEを返します。}
var
_fPat:integer;
begin
_fPat:= GetFPat(hPoly);
_SetFPat(hPoly, 0);
_if HArea(hPoly) = 0 then
__Closed:= false
_else
__Closed:= true;
_SetFPat(hPoly, fPat);
end; {Closed}

function GetNumByte(c:char):integer;
{ 文字のバイト数を返します。 }
var
_result_:integer;
begin
_case Ord(c) of
__129..159, 224..252: result:= 2;
__otherwise result:= 1;
_end;{case}_
_GetNumByte:= result;
end;{GetNumByte}

function GetColorIndex(h:handle):integer;
{ カラー番号を返します。 }
var
_result_:integer;
_r, g, b_:real;
begin
_GetPenFore(h, r, g, b);
_RGBToColorIndex(r, g, b, result);
_GetColorIndex:= result;
end;{GetColorIndex}

procedure GetHandles(var hText, hPath:handle);
{ 図形ハンドルを取得 }
var
_h_:handle;
_x1, y1, x2, y2_:real;
begin
_h:= FSActLayer;
_while (h <> nil) do begin
__if h <> nil then begin
___case GetType(h) of
____LineObj..ArcObj, RRectObj, CurveObj:
_____hPath:= h;
____TextObj:
_____hText:= h;
___end;{case}
___h:= NextSObj(h);
__end;{if}
_end;{while}
end;{GetHandles}

procedure Convert_Curve2Poly(var h:handle);
{ パス図形を多角形に変換 }
var
_x1, y1, x2, y2_:real;
_x, y_:real;
_h0_:handle;
_i_:integer;
_arcDiv_:integer;
begin
_DSelectAll;
_if GetType(h) = LineObj then begin
__GetSegPt1(h, x1, y1);
__GetSegPt2(h, x2, y2);
__OpenPoly;
__Poly(x1, y1, (x1+x2)/2, (y1+y2)/2, x2, y2);
__h:= LNewObj;
_end{if}
_else begin
__arcDiv:= GetPrefInt(55);
__if GetType(h) = ArcObj then
___SetPrefInt(55, 512)
__else
___SetPrefInt(55, 128);
__SetSelect(h);_{VW8.5〜10.5}
__Duplicate(0, 0);_{VW8.5〜10.5}
__h:= LSActLayer;_{VW8.5〜10.5}
__DoMenuTextByName('Convert to Polygons', 0);_{VW8.5〜10.5}
{__h:= MakePolygon(h);_}{ VW11 }
__SetPrefInt(55, arcDiv);
_end;{else}
_if Closed(h) then begin
__h0:= h;
__BeginPoly;
__for i:= 1 to GetVertNum(h) do begin
___GetPolyPt(h, i, x, y);
___AddPoint(x, y);
__end;{for}
__GetPolyPt(h, 1, x, y);
__AddPoint(x, y);
__EndPoly;
__h:= LNewObj;
__DelObject(h0)
_end;
end;{Convert_Curve2Poly}

procedure GetTextInformation;
{ 文字情報を取得 }
var
_i, j, n_:integer;
_c_:char;
begin
_txt_color:= GetColorIndex(hT);
_txt_vAlign:= GetTextVerticalAlign(hT);
_n:= GetTextLength(hT);
_i:= 0;
_j:= 0;
_str:= GetText(hT);
_while (i < n) & (j <= MaxIndex) do begin
__c:= copy(str, i+1, 1);
__ch_chars[j, 1]:= c;
__ch_font[j]:= GetTextFont(hT, i);
__ch_size[j]:= GetTextSize(hT, i);
__ch_style[j]:= GetTextStyle(hT, i);
__ch_numByte[j]:= GetNumByte(c);
__ch_chars[j, 1]:= copy(str, i+1, 1);
__if ch_numByte[j] = 2 then
___ch_chars[j, 2]:= copy(str, i+2, 1);
__c:= ch_chars[j, 1];
__if c = ' ' then begin
___ch_chars[j, 1]:= '.';{ WinのVW10で空白の幅がゼロになる為(Macは未確認) }
___ch_isSpace[j]:= true;
__end
__else begin
___ch_isSpace[j]:= false;
__end;{if}
__i:= i + ch_numByte[j];
__j:= j + 1;
_end;{while}
_ClrMessage;
_if (MaxIndex < j) then
__Message(MaxIndex+1, '文字以上は無視されます。');
_ch_num:= j;
end;{GetTextInformation}

procedure CreateChars;
{ 文字を生成 }
var
_x, y_:real;
_i_:integer;
begin
_TextJust(2);_{Center}
_TextVerticalAlign(txt_vAlign);
_PenFore(txt_color);
_HCenter(hP, x, y);
_for i:= 0 to ch_num-1 do begin
__TextFont(ch_font[i]);
__Textsize(ch_size[i]);
__TextOrigin(x, y);
__if ch_numByte[i] = 2 then
___CreateText(Concat(ch_chars[i, 1], ch_chars[i, 2]))
__else {ch_numByte[i] = 1}
___CreateText(ch_chars[i, 1]);
__ch_hnd[i]:= LNewObj;
__SetTextStyle(ch_hnd[i], 0, ch_numByte[i], 0);
__SetTextStyle(ch_hnd[i], 0, ch_numByte[i], ch_style[i]);
_end;{for}
end;{CreateChars}

function GetSpaceDistance(numText:integer; lng:real):real;
{ 文字間距離を取得 }
var
_result_:real;
_wd_:real;
_numSpc_:integer;
_i_:integer;
_x1, y1, x2, y2_:real;
begin
_numSpc:= 0;
_wd:= 0;
_for i:= 0 to numText-1 do begin
__GetBBox(ch_hnd[i], x1, y1, x2, y2);
__ch_wd[i]:= x2 - x1;
__if (0 < i) & (i < (lng-1)) then begin
___numSpc:= numSpc + 2*ch_numByte[i];
__end
__else begin
___numSpc:= numSpc + ch_numByte[i];
__end;
__wd:= wd + x2 - x1;
_end;{for}
_GetSpaceDistance:=(pathLen - wd) / numSpc;
end;{GetSpaceDistance}

procedure SetDistOnCurve(num:integer; lng0, spc:real);
{ 始点から文字基点までの距離を計算 }
var
_i_:integer;
begin
_ch_dist[0]:= ch_wd[0] / 2;
_for i:= 1 to num-1 do begin
__ch_dist[i]:= ch_dist[i-1] + (ch_wd[i-1] + ch_wd[i]) / 2 + spc * (ch_numByte[i-1] + ch_numByte[i]);
_end;{for}
end;{SetDistOnCurve}

procedure SetTextOrientationOnCurve(num:integer);
{ 多角形上の文字基点座標と角度を計算 }
var
_i, j, n_:integer;
_d, dd_:real;
_x0, y0, x, y_:real;
_v_:vector;
begin
_dd:= 0;
_j:= 1;
_n:= GetVertNum(hP);
_GetPolyPt(hP, j, x0, y0);
_for i:= 0 to num-1 do begin
__while (dd < ch_dist[i]) & (j < n) do begin
___j:= j + 1;
___GetPolyPt(hP, j, x, y);
___d:= Distance(x0, y0, x, y);
___dd:= dd + d;
___v[1]:= x - x0;
___v[2]:= y - y0;
___x0:= x; y0:= y;
__end;{while}
__ch_ang[i]:= Vec2Ang(v);
__ch_x[i]:= x - v[1] * (dd-ch_dist[i]) / d;
__ch_y[i]:= y - v[2] * (dd-ch_dist[i]) / d;
_{_ReDraw;_}
_end;{for}
end;{SetTextOrientationOnCurve}

procedure ArrangeChars(num:integer);
{ 文字を配置 }
var
_i_:integer;
begin
_for i:= 0 to num-1 do begin
__SetTextOrientation(ch_hnd[i], ch_x[i], ch_y[i], ch_ang[i], false);
_end;{for}
end;{ArrangeChars}

procedure ResetSpace(num:integer);
{ 「.」を空白に戻す }
var
_i_:integer;
begin
_for i:= 0 to num-1 do begin
__if ch_isSpace[i] then
___SetText(ch_hnd[i], ' ');
_end;
end;{ResetSpace}

begin{main}
_PushAttrs;
_GetHandles(hT, hP);
_if (hP = nil) | (hT = nil) then begin
__AlrtDialog(Concat('アクティブレイヤで、', LF,
___'文字と曲線を選択して実行してください。'));
_end{if}
_else begin
__GetTextInformation;
__Convert_Curve2Poly(hP);
__BeginGroup;
___CreateChars;
__EndGroup;
__hG:= LNewObj;
__pathLen:= HPerim(hP);
__spc:= GetSpaceDistance(ch_num, pathLen);
__SetDistOnCurve(ch_num, pathLen, spc);
__SetTextOrientationOnCurve(ch_num);
__ArrangeChars(ch_num);
__ResetSpace(ch_num);
__DelObject(hP);
__ResetBBox(hG);
_end;{if}
_PopAttrs;
end;{main}
Run(AlignTextOnCurve);


文字を回転するスクリプト   与太郎
email:  Wed Dec 22 12:55:13 2004

文字を各々の文字基点で回転します。
「文字の角度を設定するスクリプト」では対応できないときに使います。
絶対角度指定と相対角度(回転角)指定の違い、という意味ではなく、
角度が異なる文字を同じだけ回転させるような場合です。

procedure RotText;
{ 文字を回転する。 }
{ アクティブレイヤの文字(グループでも可)を選択して、実行する。 }
const
_TextObj = 10;
_GroupObj = 11;
var
_numText_:integer;
_angRot_:real;
_countMode_:boolean;
_
procedure DoText(h:handle);
var
_x, y, a_:real;
_flip_:boolean;
begin
_if countMode then begin
__numText:= numText + 1;
_end{if}
_else begin
__GetTextOrientation(h, x, y, a, flip);
__SetTextOrientation(h, x, y, angRot + a, flip);
_end;{else}
end;{DoText}

procedure DoInGroup(hP:handle);
var
_h_:handle;
begin
_h:= FInGroup(hP);
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextObj(h);
_end;
end;{DoInGroup}

procedure DoInLayer;
var
_h_:handle;
begin
_h:= FSActLayer;
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextSObj(h);
_end;
end;{DoInLayer}

begin
_countMode:= true;
_numText:= 0;
_DoInLayer;
__
_if numText = 0 then begin
__AlrtDialog('文字を選択してください。');
_end{if}
_else begin
__angRot:= AngDialog('文字の回転角度(dA) = ', '0.00°');
__if not DidCancel then begin
___countMode:= false;
___DoInLayer;
__end;{if}
_end;{else}
end;
Run(RotText);


均等割付文字(グループ図形)を普通の文字にする(3)   与太郎
email:  Tue Dec 21 21:25:40 2004

>文字属性(スタイル)が一文字置きにしか設定されません...
スタイルを設定する前にリセットする必要があるようです。

SetTextStyle(hT, st, lng, GetTextStyle(hC, 0));
の前に、
SetTextStyle(hT, st, lng, 0);
を入れれば良いようです。


均等割付文字(グループ図形)を普通の文字にする(2)   与太郎
email:  Tue Dec 21 8:09:25 2004

文字属性(スタイル)が一文字置きにしか設定されません...残念!


文字と基準線の間隔を調節する   与太郎
email:  Mon Dec 20 21:50:23 2004

文字の角度を設定するスクリプトを、少し直しただけです。

procedure MoveTextVertical;
{ 文字を高さ方向に移動する。 }
{ アクティブレイヤの文字(グループでも可)を選択して、実行する。 }
const
_TextObj = 10;
_GroupObj = 11;
var
_numText_:integer;
_dH_:real;
_countMode_:boolean;
_
procedure DoText(h:handle);
var
_x, y, a_:real;
_v_:vector;
_flip_:boolean;
begin
_if countMode then begin
__numText:= numText + 1;
_end{if}
_else begin
__GetTextOrientation(h, x, y, a, flip);
__v:= Ang2Vec(a+90, dH);
__x:= x + v[1]; y:= y + v[2];
__SetTextOrientation(h, x, y, a, flip);
_end;{else}
end;{DoText}

procedure DoInGroup(hP:handle);
var
_h_:handle;
begin
_h:= FInGroup(hP);
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextObj(h);
_end;
end;{DoInGroup}

procedure DoInLayer;
var
_h_:handle;
begin
_h:= FSActLayer;
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextSObj(h);
_end;
end;{DoInLayer}

begin{main}
_countMode:= true;
_numText:= 0;
_DoInLayer;
__
_if numText = 0 then begin
__AlrtDialog('文字を選択してください。');
_end{if}
_else begin
__dH:= AngDialog('文字の移動距離(dH) = ', '0.00');
__if not DidCancel then begin
___countMode:= false;
___DoInLayer;
__end;{if}
_end;{else}
end;{main}
Run(MoveTextVertical);


Re:やってはいけない割り算?   石男
email:  Mon Dec 20 15:56:18 2004

>与太郎さん
あっけないぐらい短時間で組み直せました。実際の仕事の中でテストしていきます。
どうもでした。


Re:やってはいけない割り算?   石男
email:  Mon Dec 20 9:38:03 2004

>これを10.3と10.4てな具合にしていきたいのです。
おお、間違いました...。3.3と3.4です。
一度、整数化して計算して、その後に戻せばいいんですね。そうすれば余りの計算も出
来ますね。再考してみます。


Re:やってはいけない割り算?   与太郎
email:  Sun Dec 19 20:09:29 2004

やってはいけない割り算、はゼロ除算ですが、

>10を3で割って3.3333...となりますが、
>これを10.3と10.4てな具合にしていきたいのです。
これは意味がわかりません... 
3.3と3.4の間違いだったら、
1. Int(10.0/3 * 10)/10 → 3.3、余り=6.7
2. Int( 6.7/2 * 10)/10 → 3.3、余り=3.4
3. Int( 3.4/1 * 10)/10 → 3.4、余り=0
という考え方でどうでしょうか?


均等割付文字(グループ図形)を普通の文字にする   与太郎
email:  Sun Dec 19 19:54:51 2004

グループ図形の中の文字を全て連結して、一つの文字図形にしています。

procedure Group2Text;
{ 均等割付文字(グループ図形)から、文字を抽出する }
{$ DEBUG}
const
_TextObj = 10;
_GroupObj = 11;
var
_hG, hC, hT_:handle;
_x, y_:real;
_st, ed_:integer;
_s, ss_:string;
_
function GetColorIndex(h:handle):integer;
{ カラー番号を返します。 }
var
_result_:integer;
_r, g, b_:real;
begin
_GetPenFore(h, r, g, b);
_RGBToColorIndex(r, g, b, result);
_GetColorIndex:= result;
end;{GetColorIndex}

function CountText(hG:handle):integer;
{ グループ図形の中の文字図形を数える }
var
_n_:integer;
_h_:handle;
begin
_n:= 0;
_h:= FInGroup(hG);
_while h <> nil do begin
__if GetType(h) = TextObj then
___n:= n + 1;
__h:= NextObj(h);
_end;{while}
_CountText:= n;
end;{CountText}

procedure DupTextAtrrs(hT, hC:handle; st, ed:integer);
var
_lng_:integer;
begin
_lng:= ed - st + 1;
_SetTextFont(hT, st, lng, GetTextFont(hC, 0));
_SetTextSize(hT, st, lng, GetTextSize(hC, 0));
_SetTextStyle(hT, st, lng, GetTextStyle(hC, 0));
end;{DupTextAtrrs}

begin{main}
_hG:= FSActLayer;
_if (hG <> nil) & (GetType(hG) = GroupObj) & (0 < CountText(hG)) then begin
__DSelectAll;
__ss:= '';
__st:= 0;
__hT:= nil;
__hC:= FInGroup(hG);
__while hC <> nil do begin
___if GetType(hC) = TextObj then begin
____ed:= st + GetTextLength(hC) - 1;
____s:= GetText(hC);
____if hT = nil then begin
_____ss:= s;
_____GetVCenter(x, y);
_____TextOrigin(x, y);
_____CreateText(ss);
_____hT:= LNewObj;
_____SetPenFore(hT, GetColorIndex(hC));
_____SetTextJust(hT, 2);
____end{if}
____else begin
_____ss:= Concat(ss, GetText(hC));
_____SetText(hT, ss);
____end;{else}
____DupTextAtrrs(hT, hc, st, ed);
____st:= ed + 1;
___end;{if}
___hC:= NextObj(hC);
__end;{while}
_end{if}
_else begin
__AlrtDialog('均等割付文字を選択してください。');
_end;{else}
end;{main}
Run(Group2Text);


やってはいけない割り算?   石男
email:  Sat Dec 18 10:04:27 2004

どうしても割付けプログラムを考えたいのですが、これで避けては通れない除算なんで
すが、一番の問題の余りの処理!10を3で割って3.3333...となりますが、これを10.3と
10.4てな具合にしていきたいのです。なんか、ヒントがないですか?


文字を均等配列にするスクリプト(改定版)   与太郎
email:  Fri Dec 17 20:50:34 2004

構造体をやめたので、VW8.5でも動きます。
if ch_chars[j, 1] = ' ' だとVW9で落ちるので、一旦 c に代入して、
if c = ' ' then としました。

procedure AlignText;
{ 文字を直線の長さで均等配列にする(VW8.5以降) }
{ アクティブレイヤの文字と直線を選択して実行 }
{$ DEBUG}
const
_MaxIndex = 254;
_LineObj = 2;
_TextObj = 10;
_LF = Chr(13);
_
var
_ch_numByte_:array[0..MaxIndex] of integer;
_ch_chars_:array[0..MaxIndex, 1..2] of char;
_ch_font,
_ch_size,
_ch_style_:array[0..MaxIndex] of integer;
_ch_wd_:array[0..MaxIndex] of real;
_ch_hnd_:array[0..MaxIndex] of handle;
_ch_isSpace_:array[0..MaxIndex] of boolean;
_
_txtLen_:integer;
_txtVAlign_:integer;
_txtColor_:integer;
_r, g, b_:real;
_i, j, n_:integer;
_c_:char;
_s_:string;
_h, hL, hT, hG_:handle;
_rot, lnLen_:real;
_x0, y0, x, y_:real;
_x1, y1, x2, y2_:real;
_spc, wd_:real;
_numSpc_:integer;
_
function GetNumByte(c:char):integer;
var
_result_:integer;
begin
_case Ord(c) of
__129..159, 224..252: result:= 2;
__otherwise result:= 1;
_end;{case}_
_GetNumByte:= result;
end;{GetNumByte}

begin{main}
_PushAttrs;
_{ 図形ハンドルを取得 }
_h:= FSActLayer;
_while (h <> nil) do begin
__if h <> nil then begin
___if GetType(h) = LineObj then
____hL:= h
___else if GetType(h) = TextObj then
____hT:= h;
___h:= NextSObj(h);
__end;{if}
_end;{while}
_h:= nil;
_
_DSelectAll;
_
_if (hL = nil) | (hT = nil) then begin
__AlrtDialog(Concat('アクティブレイヤで、', LF,
___'文字と直線を選択して実行してください。'));
_end{if}
_else begin
_{ 文字情報を取得 }
__GetPenFore(hT, r, g, b);
__RGBToColorIndex(r, g, b, txtColor);
__txtVAlign:= GetTextVerticalAlign(hT);
__n:= GetTextLength(hT);
__i:= 0;
__j:= 0;
__s:= GetText(hT);
__while (i < n) do begin
___c:= copy(s, i+1, 1);
___ch_chars[j, 1]:= c;
___ch_font[j]:= GetTextFont(hT, i);
___ch_size[j]:= GetTextSize(hT, i);
___ch_style[j]:= GetTextStyle(hT, i);
___ch_numByte[j]:= GetNumByte(c);
___if ch_numByte[j] = 2 then
____ch_chars[j, 2]:= copy(s, i+2, 1);
___c:= ch_chars[j, 1];
___if c = ' ' then begin{ if ch_chars[j, 1] = ' ' だとVW9で落ちる }
____ch_chars[j, 1]:= '.';{ WinのVW10で空白の幅がゼロになる為(Macは未確認) }
____ch_isSpace[j]:= true;
___end
___else begin
____ch_isSpace[i]:= false;
___end;{if}
___i:= i + ch_numByte[j];
___j:= j + 1;
__end;{while}
__txtLen:= j;
__
__{ 線情報を取得 }
__GetSegPt1(hL, x0, y0);
__GetSegPt2(hL, x, y);
__lnLen:= HLength(hL);
__rot:= HAngle(hL);
__
__{ 文字を生成 }
__TextJust(2);_{Center}
__TextVerticalAlign(txtVAlign);
__PenFore(txtColor);
__TextOrigin(x0, y0);
__BeginGroup;
__for i:= 0 to txtLen - 1 do begin
___TextFont(ch_font[i]);
___Textsize(ch_size[i]);
___if ch_numByte[i] = 2 then
____CreateText(Concat(ch_chars[i, 1], ch_chars[i, 2]))
___else {ch_numByte[i] = 1}
____CreateText(ch_chars[i, 1]);
___ch_hnd[i]:= LNewObj;
___SetTextStyle(ch_hnd[i], 0, ch_numByte[i], ch_style[i]);
__end;{for}
__EndGroup;
__hG:= LNewObj;
__
__{ 文字間距離を取得 }
__numSpc:= 0;
__wd:= 0;
__for i:= 0 to txtLen - 1 do begin
___GetBBox(ch_hnd[i], x1, y1, x2, y2);
___if (0 < i) & (i < (txtLen-1)) then begin
____numSpc:= numSpc + 2*ch_numByte[i];
___end
___else begin
____numSpc:= numSpc + ch_numByte[i];
___end;
___ch_wd[i]:= x2 - x1;
___wd:= wd + ch_wd[i];
__end;{for}
__spc:=(lnLen - wd) / numSpc;
__
__{ 文字を再配置 }
__x:= x0 + ch_wd[0]/2;
__SetTextOrientation(ch_hnd[0], x, y0, 0, false);
__for i:= 1 to txtLen - 1 do begin___
___x:= x + spc * (ch_numByte[i-1] + ch_numByte[i]) + (ch_wd[i-1]+ch_wd[i])/2;
___SetTextOrientation(ch_hnd[i], x, y0, 0, false);
__end;{for}
__
__{ 文字を回転 }
__HRotate(hG, x0, y0, rot);
__
__{ 「.」を空白に戻す }
__for i:= 0 to txtLen - 1 do begin
___if ch_isSpace[i] then
____SetText(ch_hnd[i], ' ');
__end;
_end;{if}
_PopAttrs;
end;{main}
Run(AlignText);


文字の角度を設定するスクリプト   与太郎
email:  Thu Dec 16 22:34:18 2004

文字を均等配列にするスクリプトと合わせて使えば、Macでも縦書きが出来ます。

procedure SetTextRot;
{ 文字の回転角を設定する。 }
{ アクティブレイヤの文字(グループでも可)を選択して、実行する。 }
const
_TextObj = 10;
_GroupObj = 11;
var
_numText_:integer;
_angText_:real;
_countMode_:boolean;
_
procedure DoText(h:handle);
var
_x, y, a_:real;
_flip_:boolean;
begin
_if countMode then begin
__numText:= numText + 1;
_end{if}
_else begin
__GetTextOrientation(h, x, y, a, flip);
__SetTextOrientation(h, x, y, angText, flip);
_end;{else}
end;{DoText}

procedure DoInGroup(hP:handle);
var
_h_:handle;
begin
_h:= FInGroup(hP);
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextObj(h);
_end;
end;{DoInGroup}

procedure DoInLayer;
var
_h_:handle;
begin
_h:= FSActLayer;
_while h <> nil do begin
__case GetType(h) of
___TextObj: DoText(h);
___GroupObj: DoInGroup(h);
__end;{case}
__h:= NextSObj(h);
_end;
end;{DoInLayer}

begin
_countMode:= true;
_numText:= 0;
_DoInLayer;
__
_if numText = 0 then begin
__AlrtDialog('文字を選択してください。');
_end{if}
_else begin
__angText:= AngDialog('文字の角度(A) = ', '0.00°');
__if not DidCancel then begin
___countMode:= false;
___DoInLayer;
__end;{if}
_end;{else}
end;
Run(SetTextRot);


Re: SetTextで文字列を設定するときの注意   陰陽師
email:  Thu Dec 16 16:37:17 2004

>与太郎さん
あらら、本当ですね、スクリプト終了後には文字化けこそしませんが、テキストツールで
キャレットを入れた途端に文字化けするようです。
厳密には文字属性が変更されている位置の前や途中に1Byte文字を奇数個入れると発生する
ようですね。
しかし、文字属性を残したまま SetText を迂回してコーディングするのは現実的でない
ように思います。
他の開発ツールで同様の現象が発生した場合でも、不可能ではないですが、それでもあま
りやりたくない修正ですね


Re: Text編集ダイアログ   石男
email:  Thu Dec 16 14:10:49 2004

>与太郎さん
やはり、文字はやっかいですね。通りでフォント等の指定の出来ないエディタがある訳
ですね、無理もない...。
>陰陽師さん
カスタマイズしていると見えない壁が存在していますね...。
なかなか情報が出てこないし、少ない情報も英語だし...。


SetTextで文字列を設定するときの注意   与太郎
email:  Thu Dec 16 13:06:49 2004

>陰陽師さん
SetTextで文字列を変えた時、文字属性が全部同じなら問題ないですが、
文字ごとに属性を変えてる場合、文字の挿入や削除で、文字と属性の関係がずれてしまいます。
2バイト文字が化けることもあります。
例をあげると、全部2バイト文字で、途中で属性が変化している状態で、「Text編集ダイアログ」
で先頭に1バイト文字を挿入すると、属性が2バイト文字の前半と後半で変わってしまい、その
位置の文字は化けてしまいます。属性が違うので、1バイト目と2バイト目が別の文字と認識さ
れるのが原因です。

これは、VW標準の「文字検索/置換」コマンドでも起こります。


Re: Text編集ダイアログ   陰陽師
email:  Thu Dec 16 11:37:19 2004

>石男さん

僕は Win VW10 ですが、縦スクロール○ 横スクロール× タブ入力× です。
スクロールについてはバグはバグでも TextEditBox コンポーネントのプロパティの設定
忘れでしょうね...ここいら辺はユーザーが設定できるというのが本来の姿ですが...
何でもかんでもパラメータで設定というのも無理があります。

そろそろVector Script の言語仕様もObject化の時期にきているのでは? と思うのですが...
でないと近い将来、他のCADに遅れをとることになるでしょう。
そしてSDKもいいですが、いっそのことVWがOLE対応になれば他の言語からでもVector Scriptを
使うことができ、MacのToolBox やWinのAPIも利用できるんです(^-^)

>どうもです、CreateEditTextBoxにはスクロール機能がついているんですが、VW11の
>Macではこのスクロールが出てきません。また、これもMac OS10.3がらみのバグかもし
>れません。それとTab入力は出来ない模様です、これは仕様かな。


Re: Text編集ダイアログ   陰陽
email:  Thu Dec 16 10:34:57 2004

>石男さん
おはようございます、昨日はありがとうございました。
他の言語を長い間使っていて、久しぶりにVector Scriptoに触れると非常に窮屈に感じます。
でも反対に窮屈だからこそ、何とかしょうと工夫が生まれ、皆はまって行くのかも知れませんネ。(^o^)

それとText編集ダイアログのコードは、下のままでは、コマンド実行の度にセレクション
ポインタに制御が戻るので連続して編集するのに不便です。
最終行から 4行目の SetTool(-128); を2行上に上げて下記のようにして下さい。

Warning('    文字列が大きすぎます!');
SetTool(-128);
end;
SetLayerOptions(Option);
end;
Run(TextEdit);


Re.: Text編集ダイアログ   石男
email:  Thu Dec 16 9:27:26 2004

>陰陽師さん
どうもです、CreateEditTextBoxにはスクロール機能がついているんですが、VW11の
Macではこのスクロールが出てきません。また、これもMac OS10.3がらみのバグかもし
れません。それとTab入力は出来ない模様です、これは仕様かな。
>与太郎さん
>GetPolylineVertex(h, i, x, y, tp, R);
そう、これを言ってました。頂点タイプが円弧なら円弧の半径を取れるみたいな感じ
だったので試したのですが、0しか返ってきません。SDKにも似たものがあるんですが
これは確認出来ていません...。


Text編集ダイアログ   陰陽
email:  Wed Dec 15 21:01:28 2004

こんばんわ陰陽師です。
石男さんに モダンダイアログの CreateEditTextBox( ) の使い方をご教授頂きました。
ありがとうございました。

VectorWorks のテキストツールは配置済みの文字列を編集する際、カーソルが狙った位置
に入らずいらいらします。
下のScriptは、配置済みの文字列をクリックして編集ダイアログに読込み同じ縮尺なら、
異なるレイヤへもジャンプして編集することができます。
皆さんにも、お使い頂ければ幸いです。

Procedure TextEdit;
const
MaxLen = 32000;
var
TextLen,Option: Integer;
ObjH: Handle;
PickedText,TextObj: DynArray[] of Char;
Result: Real;
IsText,NilHandle: Boolean;

procedure GetPickedText;
var
x,y: Real;
begin
GetPt(x,y);
ObjH := PickObject(x,y);
if ObjH<>Nil then
begin
NilHandle := False;
if GetType(ObjH) = 10 then
begin
IsText := True;
PickedText := GetText(ObjH);
TextLen := Len(PickedText);
end else
IsText := False;
end else
NilHandle := True;
end;

procedure EditDilg;
const
WChara = 60;
HChara = 15;
TextBoxID = 3;
var
DialogID: LongInt;
DlgJust: Boolean;

procedure DlgCallback(var Item,Value: Longint);
begin
Case Item of
SetupDialogC: SetField(TextBoxID,PickedText);
1: TextObj := GetField(TextBoxID);
end;
end;

begin
DialogID := CreateLayout(' テキスト 編集',False,'O K','Cancel');
CreateEditTextBox(DialogID,TextBoxID,'',WChara,HChara);
SetFirstLayoutItem(DialogID,TextBoxID);
DlgJust:=VerifyLayout(DialogID);
if DlgJust then
Result := RunLayoutDialog(DialogID,DlgCallback);
end;

procedure Warning(S: String);
begin
SysBeep;
AlrtDialog(Concat(Chr(32),Chr(10),Chr(32),Chr(10),S));
end;

begin
Option := GetLayerOptions;
SetLayerOptions(5);
GetPickedText;
if IsText & (NilHandle=False) & (TextLen<=MaxLen) then
begin
EditDilg;
if Result = 1 then
begin
SetText(ObjH,TextObj);
ReDrawAll;
end;
end else
begin
if (IsText=False) & (NilHandle=False) then
Warning('  文字列を指示してください!');
if (NilHandle=False)&(TextLen>MaxLen) then
Warning('    文字列が大きすぎます!');
end;
SetTool(-128);
SetLayerOptions(Option);
end;
Run(TextEdit);


曲線の円弧半径を得るには   与太郎
email:  Wed Dec 15 20:09:19 2004

石男さん、
>本日スクリプト三昧です...。
各所で大活躍ですね。

>曲線の円弧情報もとれない...。
GetPolylineVertex(h, i, x, y, tp, R);で返ってくるRは設定値で、実際にその半径か
どうか判りません(これはバグではないから、新しい別の関数でないと無理でしょう。)
データパレットの「フィレット設定」では正しい半径が出るんですから、なにか方法が
あるんでしょうけど...
曲線を線分に分解して、円弧のハンドルを取って出来ないかなあ。


Re4: 文字サイズを変えずに拡大/縮小するには?   石男
email:  Wed Dec 15 18:17:47 2004

図面承認貰えず、本日スクリプト三昧です...。いいのか悪いのか?
>VS関数にないSKD関数を、全部PIL化してもらえたら有難いのですが...
はい、確かにそうです。その前に、古くからある関数で引数のおかしいやつを直して
欲しいです。曲線の円弧情報もとれない...。
>めんどくさいですね。
かなり面倒です...。



Re3: 文字サイズを変えずに拡大/縮小するには?   与太郎
email:  Wed Dec 15 18:00:51 2004

石男さん、ありがとうございます。
勉強不足でした。

>PlugInLibraryRoutines:HScale2D();
VW10のデモ版には入ってないので、VW10.5からで間違いないようです。
小出しにせずに、VS関数にないSKD関数を、全部PIL化してもらえたら有難いのですが...

>四角形、多角形、曲線で図面を書いてGetBBoxで最小の縦横寸法をレコードに書き出します
曲線でもなんでも計算前に多角形に変換すればいいんでしょうけど、
多角形の各辺を基準にして(辺の回数だけ)回転しないと、最小高さは得られませんね。
もしも形状が凹だったら、基準線の下に頂点があるかどうかも調べて、その点と基準線の一端を結
んだ線を基準にして多角形を回転させて...

めんどくさいですね。


文字を均等配列にする(2)   与太郎
email:  Wed Dec 15 15:16:31 2004

「文字を均等配列にするスクリプト」は、
VW9でも動くはずだったのですが、そのままではダメなようです。
VW9.5(Mac)、VW9デモ(Win)共に、VWが落ちてしまいました。


Re.: 文字サイズを変えずに拡大/縮小するには?   石男
email:  Wed Dec 15 10:29:57 2004

VW10.5以降で確認したところ、PlugInLibraryRoutinesの中にこんな関数を見つけまし
た。これをつかうと大丈夫そうです。
HScale2D(h: HANDLE; centerX: REAL; centerY: REAL; scaleX: REAL; scaleY: REAL; scaleText: BOOLEAN);
ハンドル図形に対して拡大縮小をさせます。最後の引数scaleText: BOOLEANは文字に対
して実行するかということなので、これをfalseにしておいてグループ図形に対して実
行すれば均等配列が出来ますよ。


Re.: 文字サイズを変えずに拡大/縮小するには?   石男
email:  Wed Dec 15 9:27:12 2004

どうも思いつきません。
>何処へ?
四角形、多角形、曲線で図面を書いてGetBBoxで最小の縦横寸法をレコードに書き出し
ます。この時、それぞれの図形が傾いていないならOKなのですが、傾いていると意味の
ない数字になってしまいます。それぞれの図形タイプ毎に条件を付けていくと...。
それで、何処へ?行ってしまいました...。


文字サイズを変えずに拡大/縮小するには?   与太郎
email:  Tue Dec 14 20:56:08 2004

下の書き込みの均等文字列(グループ図形)の幅だけを、スクリプトで簡単に変えられないでしょうか?
手動なら問題ないのですが...
Scale()でやると、文字サイズまで変わってしまいます。

>陰陽師さん
太っ腹!
ときどきWinのNotePadでスクリプトを書いてましたが、オートインデントすらないので不便でした。
Vector Script専用 Editor、ありがたく使わせていただきます。
みなさんに成りすましまして、お礼申し上げます。

>石男さん
何処へ?
四角形の傾きについて、先日のは律儀に計算しましたが、多角形を水平に回転すれば四角形かどうかの
鑑定が簡単になるような気がしました。

>ARcoatingさん
おひさです!

>A&Bさん
どうもです。


Re.: Vector Script専用 Editor(for Win)   石男
email:  Tue Dec 14 9:08:07 2004

>陰陽師さん
すごい物を作りましたね。そのパワーには脱帽です。残念ながら私はMacなので使えな
いのですが...。
そんなMacな人にはやはり「mi」がお勧めです。A+AさんがVectorScriptモードを提供
してくれました。数年前から「mi」を愛用していますが、これで鬼に金棒です。
AppleScriptを少し分かれば「mi」のドキュメントをVectorScriptをVWで実行させるこ
とも簡単です。またテンプレートを利用するとかなり便利です。
そんな「mi」は...
http://www.mimikaki.net/


感謝。  A&B
email:  Mon Dec 13 20:07:49 2004

与太郎さん、石男さん、陰陽師さん。
ただ、ただ、感謝です。ありがとうございます。


Re^2:四角形の傾き   石男
email:  Mon Dec 13 16:47:40 2004

>与太郎さん
いつも、すみません。2Dも条件を与えていくと段々奥が深くなっていきますね。
どうも考えているところまで行けない気がしてきました。


Re:四角形の傾き   与太郎
email:  Mon Dec 13 14:10:56 2004

全部の辺の長さと角度をしらべて、幅、高さ、角度を返す関数です。

procedure test;
{$ DEBUG}
var
h:handle;
wd, ht, a:real;

function Closed(hPoly: handle): boolean;
{多角形が閉じていればTRUEを返します。}
var
fPat:integer;
begin
fPat:= GetFPat(hPoly);
SetFPat(hPoly, 0);
if HArea(hPoly) = 0 then
Closed:= false
else
Closed:= true;
SetFPat(hPoly, fPat);
end; {Closed}

function IsRectangle(h:handle; var wd, ht, ang:real):boolean;
{ 長方形の情報を返します。 }
const
PolyObj = 5;
dA = 0.0001;{degree}
var
result:boolean;
i:integer;
x, y:array[0..4] of real;
d, a:array[1..4] of real;
v:vector;
aa:real;
begin
result:= false;
if GetType(h) = PolyObj then begin
if GetVertNum(h) = 4 then begin
{if IsPolyClosed(h) then begin}
if Closed(h) then begin
for i:= 1 to 4 do
GetPolyPt(h, i, x[i], y[i]);
x[0]:= x[4]; y[0]:= y[4];
for i:= 1 to 4 do begin
d[i]:= Distance(x[i], y[i], x[i-1], y[i-1]);
v[1]:= x[i] - x[i-1]; v[2]:= y[i] - y[i-1];
a[i]:= Vec2Ang(v);
if (i = 3) | (i = 4) then begin
a[i]:= a[i] + 180;
if 180 < a[i] then
a[i]:= a[i] - 360;
end;{if}
end;{for}
if ((d[1]) = (d[3])) & ((a[1]) = (a[3])) then begin
result:= true;
aa:= a[2] - a[1] + 90;
while (180-dA) < aa do
aa:= aa - 180;
if Abs(aa) < dA then begin
wd:= d[1];
ht:= d[2];
ang:= a[2];
end;{iF}
end;{if}
end;{if}
end;{if}
end;{if}
IsRectangle:= result;
end;{IsRectangle}

begin{test}
h:= FSActLayer;
if IsRectangle(h, wd, ht, a) then
Message('Width=', wd, ' / Height=', ht, ' / Angle=', a)
else
Message('長方形ではござらん!');
end;
Run(test);

IsPolyClosed は、使えない場合もあるので、代わりにClosedを使いました。
距離の比較に「=」は、まずいかも。(誤差を考慮しないと)


Vector Script専用 Editor(for Win)   陰陽師
email:  Mon Dec 13 10:19:05 2004

1年ぶりに書き込みさせていただきます。

Vector Script専用 Editorなるものを作ってみました...
Windows版 のみなのですが Win な人は下のURLを覗いて見てください。

http://www.eonet.ne.jp/~onmyouji/VWEditor.html


四角形の傾き   石男
email:  Mon Dec 13 9:16:07 2004

四角形を傾かせると多角形になってしまいますが、それなら傾いた多角形の角度を取得
する方法ってあるんでしょうか?もしかしたら、四角形のPIOを作って...という方法し
かないんですかね?


Re.:カメラのネタ   石男
email:  Mon Dec 13 8:38:26 2004

>0,0,1とは思ってもみませんでした、、、。
マニュアルに書かれている通りにやったのでは絶対に分かりません。
たまたま、NNAのMLで見つけただけです。ホントは書き直してもらいたいところです。



re:カメラのネタ  ARcoating
email:  Sat Dec 11 19:20:17 2004

こんにちは石男さん。
情報ありがとうございます!
SetViewVectorはこうやってやれば使えるのですね!!
0,0,1とは思ってもみませんでした、、、。
石男さんのご想像通り、SetViewVectorが使えなくて、
SetViewにしました、、SetViewはほんとわけわかりません、、、。
おかげさまで、視点を自由に変えられそうです!
ありがとうございました!


カメラのネタ   石男
email:  Sat Dec 11 11:33:34 2004

>ARcoatingさん
SetViewを使うと一生懸命座標計算をしなくてはならないと思いますが、SetViewVector
を使うと楽出来ます。きっとSetViewVectorが使えず、SetViewを使うはめになったので
しょうけど...。

SetViewVector( locationX , locationY , locationZ , targetX , targetY , targetZ , upX , upY , upZ ) ;

locationカメラの座標
targetview target視点の座標
up視線角度

 となっていますが、upの引数を0,0,1にしないと駄目なようです。
以下参考になれば

Procedure Test ;

Var
gCamera , gTarget : Vector ;
gLenz : Real ;
gSave : Boolean ;
{--------------------Sub-------------------}
{-------------------------Set_Projection------------------------}
Procedure Set_Projection( Lenz_Dist : Real ) ;
Var
p1X, p1Y, p2X, p2Y , Real_Offset : Real;
Begin
GetDrawingSizeRect( p1X, p1Y, p2X, p2Y );
Real_Offset := ( 25.413 * GetLScale( ActLayer ) ) * Lenz_Dist ;
Projection( 1 , 0 , Real_Offset , p1X, p1Y, p2X, p2Y );
End ;

{=================Main===================}
Begin
gLenz := 8.5 ;
gSave := false ;
GetPt( gCamera.x , gCamera.y ) ;
GetPtL( gCamera.x , gCamera.y , gTarget.x , gTarget.y ) ;
PtDialog( 'カメラとターゲットの高さを入力 X:カメラ Y:ターゲット' , '0' , '0' , gCamera.z , gTarget.z ) ;{-----------カメラとターゲットの一致には同じ高さ-------------}
If Not DidCancel Then
Begin
Locus3D( gCamera.x , gCamera.y , gCamera.z ) ;
Locus3D( gTarget.x , gTarget.y , gTarget.z ) ;
Set_Projection( gLenz ) ;

SetViewVector( gCamera.x , gCamera.y , gCamera.z , gTarget.x , gTarget.y , gTarget.z , 0, 0 , 1 ) ;

{---------画面登録----------}
If ( gSave = true ) Then
Begin
SaveSheet( 'TestView' , true, true, true ) ;
End ;
End ;
End ;
Run( Test ) ;


ロジスティック方程式  ARcoating
email:  Fri Dec 10 22:24:28 2004

こんばんわ。おひさしぶりです。
ちょっと来てない間に与太郎さんすごいですね!!
大変貴重で有用なツールがたくさん!!
さっそく、使わせて頂きます!
私も、ツールではありませんが、スクリプトを書きましたので
書込みさせて頂きます。

内容はロジスティック方程式を解いて、それを図形化、
そして、作成過程をカメラを回して表示するものです。
QT書出しもついでにしますが、時間がかかるので
コメントアウトしました。


procedure fearful_symmetry;

const
_Pai=3.141592653589793;
var
_cA,cB,cC,cD,cK,cGyou,bairitu,copy2:real;
_cCount,zukeiiti,copy1 : integer;
_x,y,z,z_sita,drawX,drawY :real;
_draw2X,draw2Y :real;
_n,nVTR,nnVTR : integer;
_kirimu_n1,kirimu_n2 : integer;
_hn1,wsh : HANDLE;
_ZArray: ARRAY[0..100,0..100] OF real;
_{以下ビデオ用}
_filename :string;
_refa,abc :INTEGER;
_frameRate :REAL;
_keyframeRate :LONGINT;
_xAngleR, yAngelR, zAngleR, offsetX, offsetY, offsetZ:REAL;
_FrameCutNo :INTEGER;
_
{__/__/__/__/__/__/__/__/__/__/ 座標計算 __/__/__/__/__/__/__/__/__/}
PROCEDURE Logistic_Equation(var xx:real; var yy:real);
var
_x1,y1 :real;
begin
_x1:=cA*sin(2*Pai*xx)+cB*sin(2*Pai*xx)*cos(2*Pai*yy)+cC*sin(4*Pai*xx)+cD*sin(6*Pai*xx)*cos(4*Pai*yy)+cK*xx;
_if xx>=0 then
__x1:=x1-trunc(x1)
__else
__x1:=x1-trunc(x1)+1;
_y1:=cA*sin(2*Pai*yy)+cB*sin(2*Pai*yy)*cos(2*Pai*xx)+cC*sin(4*Pai*yy)+cD*sin(6*Pai*yy)*cos(4*Pai*xx)+cK*yy;
_if yy>=0 then
__y1:=y1-trunc(y1)
__else
__y1:=y1-trunc(y1)+1;
_xx:=(x1+1)*50;
_yy:=(y1+1)*50;
end;

{__/__/__/__/__/__/__/__/__/__/ 高さ(z)算出 __/__/__/__/__/__/__/__/}
PROCEDURE Z_Maker(ax,ay:LONGINT; var az:real; var bz:real);
var
_sukima: Real;
begin
_sukima := 0.1;
_IF ZArray[ax,ay]<>0 THEN
__begin
__bz := ZArray[ax,ay]+sukima;
__az := bz*bairitu+0.3;
__ZArray[ax,ay] := az;
_end else
__begin
__bz := sukima;
__az := bz+0.3;
__ZArray[ax,ay] := az;
_end;
end;

{__/__/__/__/__/__/__/__/__/__/ 3D図形を作る __/__/__/__/__/__/__/__/}
PROCEDURE Objects3D_Maker(ax,ay:LONGINT; az,bz:real);

_{__/__/__/__/__/__/__/ 色づけ __/__/__/__/__/__/__/__/__/__/}
_function Fcolor(aaz:real):LONGINT;
_var
__aa: LONGINT;
_begin
__IF aaz<0.5 THEN
___begin
___aa := round(random*191)+48;{48-239=191}
___Fcolor := aa;
__END
__ELSE BEGIN
__IF (aaz>=0.50) and (aaz<1) THEN
___begin
___aa := round(random*95)+80;
___Fcolor := aa;
__END
__ELSE BEGIN
__IF (aaz>=1) and (aaz<7) THEN
___begin
___aa := round(random*95)+112;
___Fcolor := aa;
__END
__ELSE BEGIN
___aa := round(random*95)+144;
___Fcolor := aa;
__end;
__end;
__end;
_end;

begin
_FillBack (Fcolor(az));
_PenFore (Fcolor(az));
_BeginXtrd(bz, az);
_rect(ax-0.4,ay+0.4,ax+0.4,ay-0.4);
_EndXtrd;
end;

{__/__/__/__/__/__/__/__/__/__/ カメラの動き __/__/__/__/__/__/__/__/}
procedure Camera_Move(FcNo:INTEGER; var ARx:real; var ARy:real; var ARz:real; var OSx:real; var OSy:real; var OSz:real);
_begin
__IF (FcNo>0) and (FcNo<=30) THEN
__BEGIN
___ARx := ARx+0;
___ARy := ARy+0;
___ARz := ARz+0;
___OSx := OSx+1.267;
___OSy := OSy+0.2;
___OSz := OSz-0.167;
__END
__ELSE BEGIN
__IF (FcNo>30) and (FcNo<=31) THEN
__BEGIN
___ARx := ARx+43;
___ARy := ARy+0;
___ARz := ARz+0;
___OSx := OSx+11;
___OSy := OSy-18;
___OSz := OSz+23;
__END
__ELSE BEGIN
__IF (FcNo>31) and (FcNo<=200) THEN
__BEGIN
___ARx := ARx+0;
___ARy := ARy+0;
___ARz := ARz+0;
___OSx := OSx+0;
___OSy := OSy+0;
___OSz := OSz-0.355;
__END
__ELSE BEGIN
__END;
__END;
__END;
_END;

{__/__/__/__/__/__/__/__/__/__/ メイン __/__/__/__/__/__/__/__/__/__/}
begin
_wsh := ActSSheet ;
_cGyou:=GetCellNum(wsh,28,5);
_cA:=-0.59;
_cB:=0.2;
_cC:=0.1;
_cD:=0;
_cK:=0;
_bairitu:=1.2;
_zukeiiti:=1;
_CASE zukeiiti OF
__1: begin copy1:=1; copy2:=50; cCount:=10000; nnVTR:=50; end;
_END;
_{ビデオ設定}
_xAngleR:=-43;
_yAngelR:=0;
_zAngleR:=0;
_offsetX:=-99;
_offsetY:=-38;
_offsetZ:=-8;
_{QT設定}
{_filename := Concat('C:\Program Files\VectorWorks10J',cGyou,'.mov');}
{_refa := 122;}
{_abc := QTInitialize;}
{_refa := QTOpenMovieFile(filename);}
{_QTSetMovieOptions(refa, 12, 12, TRUE, TRUE);}
_{Message(abc,' start_time_',Date(2,2));}

{_LoadCell(2,1,Date(2,2));}{レンダ時間計測用}
_x:=0.1;
_y:=0.3;
_for n:=1 to 20 do
_begin
__Logistic_Equation(x,y);
_end;
_QTWriteFrame(refa);
_for n:=1 to cCount do
_begin
__nVTR := nVTR+1;
__Logistic_Equation(x, y);
__drawX := round(x);
__drawY := round(y);
__for kirimu_n1:=1 to copy1 do
__begin
___CASE kirimu_n1 OF
____1: draw2X:=drawX;
____2: draw2X:=drawX+copy2;
___END;
___for kirimu_n2:=1 to copy1 do
___begin
____CASE kirimu_n2 OF
_____1: draw2Y:=drawY;
_____2: draw2Y:=drawY+copy2;
____END;
____if (draw2X>100) or (draw2Y>100) then
____begin end
____else begin
____Z_Maker(draw2X, draw2Y, z, z_sita);
____Objects3D_Maker (draw2X, draw2Y, z, z_sita);
____hn1 := LNewObj;
____SetDSelect(hn1);
____end;
___end;
__end;
__if nVTR=nnVTR then
___begin
___FrameCutNo := FrameCutNo+1;
___Camera_Move (FrameCutNo, xAngleR, yAngelR, zAngleR, offsetX, offsetY, offsetZ);
___SetView (xAngleR, yAngelR, zAngleR, offsetX, offsetY, offsetZ);
___ReDrawAll;
{___QTWriteFrame(refa);}{QT設定中間}
___nVTR := 0;
__END
__ELSE BEGIN
__end;
__{Message(n);}
_end;
{_QTCloseMovieFile(refa);} {QT設定中間}
{_QTTerminate;}
{_LoadCell(2,3,Date(2,2));}{レンダ時間計測用}
_{ClrMessage;}
end;
run(fearful_symmetry);


文字を均等配列にする   与太郎
email:  Fri Dec 10 19:46:11 2004

アクティブレイヤの文字と直線を選択して実行します。
直線を基準線にした均等配列文字(グループ図形)が出来ます。

procedure AlignText;
{ 文字を直線の長さで均等配列にする(VW9以降) }
{ アクティブレイヤの文字と直線を選択して実行 }
{$ DEBUG}
const
_LineObj = 2;
_TextObj = 10;
_LF = Chr(13);
_
type
_charInfo = structure
__numByte_:integer;
__chars_:array[1..2] of char;
__font, size, style_:integer;
__x1, x2_:real;
__hnd_:handle;
__isSpace_:boolean;
_end;
_
var
_txt_:array[0..254] of charInfo;
_txtLen_:integer;
_txtVAlign_:integer;
_txtColor_:integer;
_r, g, b_:real;
_i, j, n_:integer;
_c_:char;
_s_:string;
_h, hL, hT, hG_:handle;
_rot, lnLen_:real;
_x0, y0, x, y_:real;
_x1, y1, x2, y2_:real;
_spc, wd_:real;
_numSpc_:integer;
_
function GetNumByte(c:char):integer;
var
_result_:integer;
begin
_case Ord(c) of
__129..159, 224..252: result:= 2;
__otherwise result:= 1;
_end;{case}_
_GetNumByte:= result;
end;{GetNumByte}

begin{main}
_PushAttrs;
_{ 図形ハンドルを取得 }
_h:= FSActLayer;
_while (h <> nil) do begin
__if h <> nil then begin
___if GetType(h) = LineObj then
____hL:= h
___else if GetType(h) = TextObj then
____hT:= h;
___h:= NextSObj(h);
__end;{if}
_end;{while}
_h:= nil;
_
_if (hL = nil) | (hT = nil) then begin
__AlrtDialog(Concat('アクティブレイヤで、', LF,
___'文字と直線を選択して実行してください。'));
_end{if}
_else begin
_{ 文字情報を取得 }
__GetPenFore(hT, r, g, b);
__RGBToColorIndex(r, g, b, txtColor);
__txtVAlign:= GetTextVerticalAlign(hT);
__n:= GetTextLength(hT);
__i:= 0;
__j:= 0;
__s:= GetText(hT);
__while (i < n) do begin
___c:= copy(s, i+1, 1);
___txt[j].chars[1]:= c;
___txt[j].font:= GetTextFont(hT, i);
___txt[j].size:= GetTextSize(hT, i);
___txt[j].style:= GetTextStyle(hT, i);
___txt[j].numByte:= GetNumByte(c);
___txt[j].chars[1]:= copy(s, i+1, 1);
___if txt[j].numByte = 2 then
____txt[j].chars[2]:= copy(s, i+2, 1);
___if txt[j].chars[1] = ' ' then begin
____txt[j].chars[1]:= '.';{ 空白の幅がゼロになる為(WinのVW10で、Macは未確認) }
____txt[j].isSpace:= true;
___end
___else begin
____txt[j].isSpace:= false;
___end;{if}
___i:= i + txt[j].numByte;
___j:= j + 1;
__end;{while}
__txtLen:= j;
__
__{ 線情報を取得 }
__GetSegPt1(hL, x0, y0);
__GetSegPt2(hL, x, y);
__lnLen:= HLength(hL);
__rot:= HAngle(hL);
__
__{ 文字を生成 }
__TextJust(2);_{Center}
__TextVerticalAlign(txtVAlign);
__PenFore(txtColor);
__BeginGroup;
__for i:= 0 to txtLen - 1 do begin
___TextFont(txt[i].font);
___Textsize(txt[i].size);
___x:= x0 + lnLen/txtLen*(i+0.5);
___TextOrigin(x, y0);
___if txt[i].numByte = 2 then
____CreateText(Concat(txt[i].chars[1], txt[i].chars[2]))
___else {txt[i].numByte = 1}
____CreateText(txt[i].chars[1]);
___txt[i].hnd:= LNewObj;
___SetTextStyle(txt[i].hnd, 0, txt[i].numByte, txt[i].style);
__end;{for}
__EndGroup;
__hG:= LNewObj;
__
__{ 文字間距離を取得 }
__numSpc:= 0;
__wd:= 0;
__for i:= 0 to txtLen - 1 do begin
___GetBBox(txt[i].hnd, txt[i].x1, y1, txt[i].x2, y2);
___if (0 < i) & (i < (txtLen-1)) then begin
____numSpc:= numSpc + 2*txt[i].numByte;
___end
___else begin
____numSpc:= numSpc + txt[i].numByte;
___end;
___wd:= wd + txt[i].x2 - txt[i].x1;
__end;{for}
__spc:=(lnLen - wd) / numSpc;
__
__{ 文字を再配置 }
__HMove(txt[0].hnd, x0 - txt[0].x1, 0);
__for i:= 1 to txtLen - 1 do begin
___GetBBox(txt[i-1].hnd, x1, y1, x2, y2);
___x:= x2 + spc * (txt[i-1].numByte + txt[i].numByte);
___HMove(txt[i].hnd, x - txt[i].x1, 0);
__end;{for}
__
__{ 文字を回転 }
__HRotate(hG, x0, y0, rot);
__
__{ 「.」を空白に戻す }
__for i:= 0 to txtLen - 1 do begin
___if txt[i].isSpace then
____SetText(txt[i].hnd, ' ');
__end;
_end;{if}
_PopAttrs;
end;{main}
Run(AlignText);

普通の文字図形と違って、幅を変えると文字間隔が変わります。
斜めの場合は,基準線といっしょに選択すれば、ドラッグで幅を変えられます。
環境設定で、「文字を反転禁止」にして水平反転すると、文字が逆順になります。
(意味があるか判りませんが...)

グループの中身は一文字ずつに分解されているので、文字の編集は無理です。
プラグインオブジェクトにすれば、文字の編集は出来るようになりますが、
属性(フォント、サイズ,スタイル)を文字ごとに変えられなくなります。


名前をワークシートに書き出す。   与太郎
email:  Sun Dec 5 22:01:20 2004

名前と図形タイプを、ワークシートに書き出します。

procedure ObjNameList;
{ VWの書類で使われてる名前をワークシートに書き出す。 }
{$ DEBUG}
const
_WSName = 'Name List';
_WSheet = 18;
_MaxRow = 4094;
_Clm_Name = 1;
_Clm_TypeID = 2;
_Clm_TypeNm = 3;
_SQ = Chr(39);{ ' }
_LF = Chr(13);{ 改行 }

var
_h, hWS_:handle;
_name_:string;
_numRow, numClm_:integer;
_i, numName_:integer;
_formula_:string;

function GetTypeName(i:integer):string;
var
_result_:string;
begin
_case i of
__2: result:= '直線';
__3: result:= '四角形';
__4: result:= '長円';
__5: result:= '多角形';
__6: result:= '円/円弧';
__8: result:= 'フリーハンド';
__9: result:= '3D 基準点';
__10: result:= '文字列';
__11: result:= 'グループ';
__12: result:= '四分円';
__13: result:= '隅の丸い四角形';
__14: result:= 'ビットマップ';
__15: result:= 'シンボル';
__16: result:= 'シンボル定義';
__17: result:= '2D 基準点';
__18: result:= 'ワークシート';
__21: result:= '曲線';
__22: result:= 'PICT';
__24: result:= '柱状体';
__25: result:= '3D 多角形';
__29: result:= 'リンク図形';
__31: result:= 'レイヤ';
__34: result:= '回転体';
__38: result:= '多段柱状体';
__40: result:= 'メッシュ';
__41: result:= 'メッシュの頂点';
__47: result:= 'レコード定義';
__48: result:= 'レコード';
__49: result:= 'ドキュメントスクリプト';
__51: result:= 'スクリプトパレット';
__56: result:= 'ワークシート図形';
__63: result:= '寸法線';
__66: result:= 'ハッチング定義';
__68: result:= '壁';
__71: result:= '柱、床、屋根';
__81: result:= '光源';
__82: result:= '屋根';
__83: result:= '屋根';
__84: result:= 'ソリッドモデラー';
__86: result:= 'プラグインオブジェクト';
__87: result:= 'ドーマー、スカイライト';
__89: result:= '円弧壁';
__92: result:= 'シンボルフォルダ';
__93: result:= 'テクスチャ';
__94: result:= 'クラス定義';
__97: result:= 'テクスチャ定義';
__95: result:= '球、半球、円錐';
__111: result:= 'NURBS曲線';
__113: result:= 'NURBS曲面';
__119: result:= 'イメージ定義';
__120: result:= 'グラデーション定義';
__121: result:= 'フィル空間';
__otherwise result:= '未定義';
_end;{case}
_GetTypeName:= result;
end;{GetTypeName}

begin{main}
_numName:= NameNum;
_if (MaxRow-1) < numName then begin
__AlrtDialog(Concat('名前が多すぎます。 ', LF, MaxRow-1, '個以上は表示出来ません。'));
__numName:=MaxRow - 1;
_end;{if}
_
_{ WSを選択/作成 }
_hWS:= GetObject(WSName);
_if (hWS <> nil) & (GetType(hWS) = WSheet) then begin
__GetWSRowColumnCount(hWS, numRow, numClm);
__if (numName+1) < numRow then
___DeleteWSRows(hWS, numRow, numRow-numName-1)
__else if numRow < (numName+1) then
___InsertWSRows(hWS, numRow, numName+1-numRow);
_end{if}
_else begin
__name:= WSName;
__i:= 0;
__while (hWS <> nil) do begin
___i:= i + 1;
___name:= Concat(WSName, '-', Num2Str(0, i));
___hWS:= GetObject(name);
__end;{while}
__if hWS = nil then
___hWS:= CreateWS(name, numName+1, Clm_TypeNm);
__SetWSCellFormula(hWS, 1, Clm_Name, 1, Clm_Name, '名前');
__SetWSCellFormula(hWS, 1, Clm_TypeID, 1, Clm_TypeID, '図形タイプ');
_end;{else}
_
_{ WSに記入 }
_for i:= 1 to numName do begin
__name:= Index2Name(i);
__formula:= Concat('=', SQ, name, SQ);
__SetWSCellFormula(hWS, i+1, Clm_Name, i+1, Clm_Name, formula);
__h:= GetObject(name);
__formula:= Num2Str(0, GetType(h));
__SetWSCellFormula(hWS, i+1, Clm_TypeID, i+1, Clm_TypeID, formula);
__formula:= Concat(':', GetTypeName(GetType(h)));
__SetWSCellFormula(hWS, i+1, Clm_TypeNm, i+1, Clm_TypeNm, formula);
_end;{for}
_ShowWS(hWS, true);
end;{main}
Run(ObjNameList);

ファイル名とレイヤ名は別扱いのようで、名前のリストには入っていません。
でも、クラス名は入っています。(入ってなくてもいいと思うんですが)
仕事で作ったファイルだと、名前がたくさん付いてるのが判ります。
あと、名前を消すと、そのindexは新しく名前が付けられたときのために空い
たままになるようです。


図面上の文字をワークシートにコピーする   与太郎
email:  Fri Dec 3 22:31:51 2004

「ワークシートの文字を(図面に)描く」の逆バージョンです。
図面上でクリックした文字を、ワークシートの選択セルにコピーします。
文字属性はコピーしません。

SetWSSelection で警告を出さなくする方法がわからなかったので、SetPref(21, false); で
環境設定の「VectorScriptの警告を表示」をOFFにしています。
というか、実行中にわざと警告を出すようなスクリプトもあるので、デバッグ中でなければ
「VectorScriptの警告を表示」させないほうが良いようです。

procedure CopyText2SelCell;{ 選択セルに、クリックした文字をコピーします。(VW9以降対応) }
{$ DEBUG}
const
_TextObj = 10;
var
_hWS, hTx, h, h0_:handle;
_row, maxRow, row0,
_clm, maxClm, clm0,
_top, left,
_topSub, bottom, right, botSub_:integer;
_x, y_:real;
_str_:string;
begin
_hWS:= ActSSheet;
_if hWS = nil then begin
__AlrtDialog('ワークシートを開いてください。');
_end{if}
_else begin
__SetPref(21, false);{ 環境設定の「VectorScriptの警告を表示」をOFFにする }
__DSelectAll;
__GetWSRowColumnCount(hWS, maxRow, MaxClm);
__GetWSSelection(hWS, row, clm, top, left, topSub, bottom, right, botSub);
__row0:= row;
__clm0:= clm;
__Message('文字をクリックしてください。 空クリックで終了します。');
__GetPt(x, y); h:= PickObject(x, y);
__h0:= h;
__if (h = nil) | (GetType(h) <> TextObj) then begin
___AlrtDialog('文字をクリックしてください。');
__end{if}
__else begin
___if (top = bottom) & (left = right) then begin
____top:= 1; Left:= 1; bottom:= maxRow; right:= maxClm;
____SetWSSelection(hWS, row, clm, top, left, topSub, bottom, right, botSub);
___end;
___repeat
____str:= GetText(h);
____SetWSCellFormula(hWS, row, clm, row, clm, str);
____clm:= clm + 1;
____if clm > right then begin
_____clm:= left;
_____row:= row + 1;
_____if row >bottom then begin
______row:= top;
_____end;{if}
____end;{if}
____SetWSSelection(hWS, row, clm, top, left, topSub, bottom, right, botSub);
____DSelectObj(h0);
____h0:= h;
____SetSelect(h);
____ReDraw;
____if (row = row0) & (clm = clm0) then begin
_____h:= nil;
____end{if}
____else begin
_____GetPt(x, y);
_____h:= PickObject(x, y);
____end;{else}
___until (h = nil) | (GetType(h) <> TextObj);
__end;{else}
__ClrMessage;
_end;{else}
end;
Run(CopyText2SelCell);

これで「図面の中の表をワークシート化するスクリプト」の何パーセントかは実現したかなぁ?


螺旋形の3D多角形を作る。   与太郎
email:  Mon Nov 29 22:50:38 2004

このスクリプトを作るには、Excelで座標計算をして結果をスクリプトにするのと、
普通にスクリプトを書くのと、2つの方法があります。

1. Excelでスクリプト(3D多角形生成文)を書く方法です。
3D多角形を作るスクリプトは、Poly(X1, Y1, Z1, X2, Y2, Z3...Xn, Yn, Zn); です。
まずはExcelに下のようなデータを打ち込みます。

角度 R  H
0  0  60
30  2  55
60  4  50
90  6  45
120 8  40
150 10 35
180 12 30
210 14 25
240 16 20
270 18 15
300 20 10
330 22  5
360 24  0

上のデータから、座標を計算して下のスクリプトを作ります。(度とラジアンに注意)
Excelなら簡単に出来ます。VWのワークシートでも可能です。

Poly3D(
0.00 , 0.00 , 60.00 ,
1.73 , 1.00 , 55.00 ,
2.00 , 3.46 , 50.00 ,
0.00 , 6.00 , 45.00 ,
-4.00 , 6.93 , 40.00 ,
-8.66 , 5.00 , 35.00 ,
-12.00 , 0.00 , 30.00 ,
-12.12 , -7.00 , 25.00 ,
-8.00 , -13.86 , 20.00 ,
0.00 , -18.00 , 15.00 ,
10.00 , -17.32 , 10.00 ,
19.05 , -11.00 , 5.00 ,
24.00 , 0.00 , 0.00 );

2. 普通にPascal形式のスクリプトを書きます。
ダイアログやワークシートでパラメータを設定するスクリプトは長くなるので、
ここではスクリプトの定数を直接書き換えて設定を変えます。

Procedure Spiral;
{ 螺旋形の3D多角形を作ります }
{ パラメータはconstで設定します }
const{ ここでパラメータを設定します }
StartA = 0; { 開始角度 }
EndA = 360; { 終了角度 }
StartR = 0; { 開始半径 }
EndR = 24; { 終了半径 }
StartH = 60; { 開始高さ }
EndH = 0; { 終了高さ }
N = 12; { 分割数 }
var
x, y, z:real;
dA, a:real;
dR, r:real;
dH:real;
i:integer;
begin
dA:= (EndA - StartA) / N;
dR:= (EndR - StartR) / N;
dH:= (EndH - StartH) / N;
BeginPoly3D;
for i:= 0 to N do begin
a:= Deg2Rad(StartA + i * dA);
r:= StartR + i * dR;
x:= r * Cos(a);
y:= r * Sin(a);
z:= StartH + i * dH;
Add3DPt(x, y, z);
end;{while}
EndPoly3D;
end;
Run(Spiral);

スクリプトが出来たら、VWのリソースパレット/プラウザでVectorScriptコマンドを作って、
VectorScriptエディタにスクリプトを貼り付けます。
上の右側にあるコンパイル・ボタンを押して、エラーが出なければOKです。
定数を変えたりスクリプトを貼りかえるときは、コマンドパレット上のコマンドを、Alt/option
キーを押してダブルクリックします。VectorScriptエディタが開きます。


クラスの線幅を設定する   与太郎
email:  Sun Nov 28 22:00:37 2004

下の書き込みのスクリプトでWSを作って、線幅の数字を変えてから実行してください。

procedure SetClassLW;
{ クラスの線幅をワークシートで設定した値に設定します。 }
{$ DEBUG}
const
_WSName = 'Class LW List';
_WSheet = 18;
_ClmCls = 1;
_ClmLW = 2;
_LF = Chr(13);{ 改行 }
var
_hWS_:handle;
_name_:string;
_maxRow, maxClm_:integer;
_i, wd_:integer;

begin{main}
_hWS:= GetObject(WSName);
_if (hWS = nil) | (GetType(hWS) <> 18) then begin
__AlrtDialog(Concat('「', WSName, 'というWSがありません。',
___ LF, 'WSの名前を変えるか、新しいWSを作ってください。'));
_end{if}
_else begin
__GetWSRowColumnCount(hWS, maxRow, maxClm);
__for i:= 2 to maxRow do begin
___GetWSCellString(hWS, i, ClmCls, name);
___wd:= Round(GetCellNum(hWS, i, ClmLW));
___SetClLW(name, wd);
__end;{for}
__ShowWS(hWS, true);
_end;{else}
_
end;{main}
Run(SetClassLW);

クラスの線色や面属性を再設定するように修正するのも簡単そうです。


クラスの線幅をワークシートに書き出す   与太郎
email:  Sun Nov 28 21:53:09 2004

VW談話室より。
>壁や柱とかのクラスごとに線の太さをそのつど変更しています。
スクリプトで一度に変更してみましょうか。
まず、クラスごとの線幅をWSに書き出してみます。

procedure CreateClassLWList;
{ クラスの線幅をワークシートに書き出します。 }
{$ DEBUG}
const
_WSName = 'Class LW List';
_WSheet = 18;
_ClmCls = 1;
_ClmLW = 2;
_SQ = Chr(39);{ ' }
var
_hWS_:handle;
_name_:string;
_maxRow, maxClm_:integer;
_i, nC_:integer;
_formula_:string;

begin{main}
_nC:= ClassNum;
_
_{ WSを選択/作成 }
_hWS:= GetObject(WSName);
_if (hWS <> nil) & (GetType(hWS) = 18) then begin
__GetWSRowColumnCount(hWS, maxRow, maxClm);
__if (nC+1) < maxRow then
___DeleteWSRows(hWS, maxRow, maxRow-nC-1)
__else if maxRow < (nC+1) then
___InsertWSRows(hWS, maxRow, nC+1-maxRow);
_end{if}
_else begin
__name:= WSName;
__i:= 0;
__while (hWS <> nil) do begin
___i:= i + 1;
___name:= Concat(WSName, '-', Num2Str(0, i));
___hWS:= GetObject(name);
__end;{while}
__if hWS = nil then
___hWS:= CreateWS(name, nC+1, 2);
__SetWSCellFormula(hWS, 1, ClmCls, 1, ClmCls, 'Class名');
__SetWSCellFormula(hWS, 1, ClmLW, 1, ClmLW, '線幅');
_end;{else}
_
_{ WSに記入 }
_for i:= 1 to nC do begin
__name:= ClassList(i);
__formula:= Concat('=', SQ, name, SQ);
__SetWSCellFormula(hWS, i+1, ClmCls, i+1, ClmCls, formula);
__formula:= Num2Str(0, GetClLW(name));
__SetWSCellFormula(hWS, i+1, ClmLW, i+1, ClmLW, formula);
_end;{for}
_ShowWS(hWS, true);
end;{main}
Run(CreateClassLWList);


スクリプトでレイヤを削除する。   与太郎
email:  Thu Nov 25 20:28:30 2004

他の図形と同じように、レイヤもスクリプトで削除できます。

procedure DelLayer;
{ アクティブレイヤを(空なら)削除します。 }
{ アクティブレイヤが空でないか、レイヤがひとつしかない場合は削除しません。 }
var
hAL, hL:handle;
name:string;
begin
hAL:= ActLayer;
name:= GetLName(hAL);
hL:= FLayer;
while (hL <> nil) & (hL = hAL) do
hL:= NextLayer(hL);
if hL <> nil then begin
if NumObj(hAL) = 0 then begin
Layer(GetLName(hL));
DelObject(hAL);
AlrtDialog(Concat('レイヤ「', name, '」を削除しました。'));
end{if}
else begin
AlrtDialog(Concat('レイヤ「', name, '」は空でないので削除しません。'));
end;{else}
end{if}
else begin
AlrtDialog(Concat('他にレイヤがないので、レイヤ「', name, '」は削除出来ません。'));
end;{else}
end;
Run(DelLayer);


レイヤ情報を取得して色々と...   与太郎
email:  Wed Nov 24 22:42:15 2004

アクティブレイヤの情報を表示します。

procedure MsgLayerInfo;
{ メッセージウインドウにアクティブレイヤの情報を表示します。 }
var
_hL_:handle;
_vis_:integer;
_lVis_:string;
_ht, dHt_:real;
_xA, yA, zA_:real;
_xD, yD, zD_:real;
begin
_hL:= ActLayer;
_vis:= GetLVis(hL);
_case vis of
__0: lVis:= 'ShowLayer';
__2: lVis:= 'GrayLayer';{ ※注意 }
__-1: lVis:= 'HideLayer';{ ※注意 }
_end;{case}
_GetZVals(ht, dHt);
_GetView(xA, yA, zA, xD, yD, zD);
_Message(GetLScale(hL), ' : S=1/', GetLScale(hL),
__' (', lVis, ') : H=', ht, ' : dH=', dHt,
__' : xA=', xA, ' : yA=', yA, ' : zA=', zA,
__' : xD=', xD, ' : yD=', yD, ' : zD=', zD);
end;
Run( MsgLayerInfo);

残念ながら、レイヤの表示モードとカラー属性はVSでは取得できません。

※注意:GetLVisの返り値が、VW9までのマニュアルでは間違っています。
マニュアル→ 表示:0 /グレイ表示:1 /非表示:2
正しくは → 表示:0 /グレイ表示:2 /非表示:-1
VW10でも、スクリプトエディタの「手続き/関数...」の中の説明は間違っています。

つぎに、レイヤ情報をファイルに書き出してみます。
書き出すだけでは芸がないので、他のファイルで読み込んで同じレイヤを作れるようにします。

procedure GetLayerInfoAsScript;
{ VWフォルダの「Output.txt」にレイヤ生成のスクリプトを書き出します。 }
const
_SQ = Chr(39);
var
_hL, hAL_:handle;
_name_:string;
_scale_:real;
_vis_:integer;
_ht, dHt_:real;
_xA, yA, zA_:real;
_xD, yD, zD_:real;

{ AddSQ関数は、ここに書いてください。前の書き込みにあります。 }

begin{main}
_hAL:= ActLayer;
_hL:= FLayer;
_while hL <> nil do begin
__{ レイヤ情報を取得する。 }
__name:= GetLName(hL);{ 必要なら name:= AddSQ(GetLName(hL)); に書き換えてください。 }
__scale:= GetLScale(hL);
__vis:= GetLVis(hL);
__Layer(name);
__GetZVals(ht, dHt);
__GetView(xA, yA, zA, xD, yD, zD);
__
__{ スクリプトを書き出す。 }
__WriteLn('Layer(', SQ, name, SQ, ');');
__WriteLn('SetScale(', Scale, ');');
__case vis of
___0: WriteLn('ShowLayer;');
___2: WriteLn('GrayLayer;');
___-1: WriteLn('HideLayer;');
__end;{case}
__WriteLn('SetView(', xA, ', ', yA, ', ', zA, ', ', xD, ', ', yD, ', ', zD, ');');
__if (xA = 0) & (yA = 0) & (zA = 0) then
___WriteLn('DoMenuTextByName(''Standard Views'', 1);');{ ビューが「真上から」の場合は2D表示に設定 }
__WriteLn;
__
__hL:= NextLayer(hL);
_end;{while}
_
_{ アクティブレイヤを元にもどす。 }
_Layer(GetLName(hAL));
_name:= GetLName(hAL);
_WriteLn('Layer(', SQ, name, SQ, ');');
end;{main}
Run(GetLayerInfoAsScript);

「Output.txt」の中身はスクリプトになっていますので、VectorScriptとして取り込むか、
コマンドを作って貼り付ければ、別のファイルに同じ名前/縮尺/高さ/ビューのレイヤが
作れます。

書いてて思ったのですが,チャンクメニューの選択項目をVSから調べる方法はないですかね?


各レイヤの図形数を調べる(2)   与太郎
email:  Mon Nov 22 22:02:10 2004

アクティブレイヤだけなら、こんな風にできます。

Message(GetLName(ActLayer), ' : Objects = ', NumObj(ActLayer));

グループ内の図形もカウントするなら、下のようになります。

procedure MsgObjNum;
var
name:string;
begin
name:= GetLName(ActLayer);
Message(GetLName(ActLayer), ' : Objects = ', Count(L=name));
end;
Run(MsgObjNum);


各レイヤの図形数を調べる   与太郎
email:  Sun Nov 21 21:23:41 2004

各レイヤの図形数を調べます。何かの役には立つでしょう。

procedure GetObjNum;
{ 各レイヤの図形数を「Output.txt」に書き出します。 }
{ グループ図形の中の図形はカウントされません。 }
var
_hL_:handle;
begin
_Write('Layer'); Tab(1);
_WriteLn('Objects');
_hL:= FLayer;
_while hL <> nil do begin
__Write(GetLName(hL)); Tab(1);
__WriteLn(NumObj(hL));
__hL:= NextLayer(h);
_end;{while}
end;
Run(GetObjNum);


procedure ObjNumList;
{ 各レイヤの図形数をワークシートに書き出します。 }
{ グループ図形の中の図形もカウントされます。 }
{ WSメニューの「再計算」で表示を更新できます。 }
{$DEBUG}
const
_WSName = 'Object Num List';
_WSheet = 18;
_ClmLyr = 1;
_ClmNum = 2;
_SQ = Chr(39);{ ' }
var
_hWS, hL_:handle;
_name_:string;
_row, clm_:integer;
_i, nL_:integer;
_formula_:string;

function AddSQ(s:string):string;
{ 名前の中の「'」を「'」+「'」 に直します。 }
var
_result_:string;
_i, j, lng_:integer;
begin
_result:= s;
_lng:= Len(result);
_i:= 1;
_while (i <= lng) do begin
__if Copy(result, i, 1) = SQ then begin
___result:= Concat(Copy(result, 1, i), SQ, Copy(result, i+1, lng-i));
___lng:= lng + 1;
___i:= i + 2;
__end{if}
__else begin
___i:= i + 1;
__end;{else}
_end;{while}
_AddSQ:= result;
end;{AddSQ}

begin{main}
_nL:= NumLayers;
_
_{ WSを選択/作成 }
_hWS:= GetObject(WSName);
_if (hWS <> nil) & (GetType(hWS) = 18) then begin
__GetWSRowColumnCount(hWS, row, clm);
__if (nL+1) < row then
___DeleteWSRows(hWS, nL+1, row-nL-1)
__else if row < (nL+1) then
___InsertWSRows(hWS, row, nL+1-row);
_end{if}
_else begin
__name:= WSName;
__i:= 0;
__while (hWS <> nil) do begin
___i:= i + 1;
___name:= Concat(WSName, '-', Num2Str(0, i));
___hWS:= GetObject(name);
__end;{while}
__hWS:= CreateWS(name, nL+1, 2);
__SetWSCellFormula(hWS, 1, ClmLyr, 1, ClmLyr, 'Layer');
__SetWSCellFormula(hWS, 1, ClmNum, 1, ClmNum, 'Objects');
_end;{else}
_
_{ WSに記入 }
_i:= 0;
_hL:= FLayer;
_while hL <> nil do begin
__i:= i + 1;
__name:= GetLName(hL);{ ※注意 }
__formula:= Concat('=', SQ, name, SQ);
__SetWSCellFormula(hWS, i+1, ClmLyr, i+1, ClmLyr, formula);
__formula:= Concat('=Count(L=', SQ, name, SQ, ')');
__SetWSCellFormula(hWS, i+1, ClmNum, i+1, ClmNum, formula);
__hL:= NextLayer(hL);
_end;{while}
_ShowWS(hWS, true);
end;{main}
Run(ObjNumList);

※注意:レイヤ名に「'」が含まれているときは、下のようにしないと表示できません。
__name:= GetLName(hL);{ ※注意 }
__ ↓
__name:= AddSQ(GetLName(hL));

>石男さん
クラシック(環境)はダメですか?
与太郎はResEdit、Resorcererはクラシック環境です。


Re^2:リソース編集   石男
email:  Sat Nov 20 16:16:32 2004

>Mac OS9でResEditを使うのも最近は嫌気がさしてきました
Mac OS9で起動し直すのが嫌で嫌で...、ResFoolは編集するにはいいのだけど...。
結局、Mac OS9でResEditがベストなのかな〜。Resorcererは高過ぎ!


Re:リソース編集   与太郎
email:  Fri Nov 19 22:13:09 2004

>リソース編集をみなさんは何を使っているのでしょうか?
ResEditとResorcerer2.0(古!)ですが、
最近ほとんど使ってなくて、ResEditでファイルタイプを直したり、VWのダイアログを広げる程度。

>Mac OS9でResEditを使うのも最近は嫌気がさしてきました
OS9とResEditのどちらがイヤでしょうか?
'STR#'リソースとかを大量に作るのなら、リソースエディタよりリソースコンパイラのほうが楽
かもしれません。(どこで入手するかが問題ですが)

最近SDKについて調べてましたが、Plug-in Libraryを作れば、SDKの関数をVSから使えるようです。
例のIsPolyClosedは、SDKのGetPolyShapeCloseを呼んでるだけのような気がします。
GetProjection、GetDashPatというSDK関数を呼ぶPlug-in Libraryを作れば、VSの中でレイヤの表
示状態(2D or 3D)や破線間隔を知ることができるのですが、
CodeWarriorは古いのしか持ってないし...
CodeWarriorの新しいの高価いし!!
年貢の納め時ですし...
というわけで、今まで粘ってみましたが、来週V-Upしますよ。


リソース編集   石男
email:  Fri Nov 19 11:15:27 2004

リソース編集をみなさんは何を使っているのでしょうか?
MacWinでは違うはずですが、Mac OS9でResEditを使うのも最近は嫌気がさしてきました
Mac OSXでリソースラとなるんでしょうが、リソースラは高いし...。
OSXで使えるResFoolっていうこともあるんですが、これはイマイチです。


Re7:マニュアルについて   与太郎
email:  Sat Nov 13 16:41:36 2004

>MacOS9の環境とResEdit使いなら
古いリソースラで直接Excelに(50回くらい)コピペして、マクロの自動記録/実行で
説明文をB列に移動&1行削除。バージョン情報のテーブルを別のシートに作って、
VLOOKUPで参照しました。
コピペよりスクリプトのほうが楽そうですね。


Re6:マニュアルについて   石男
email:  Sat Nov 13 15:48:01 2004

>このPDFの大元は、与太郎が使ったのとおなじものかも。
MacOS9の環境とResEdit使いなら、分かります...。
コピーしたrsrcファイルをPlugInsに入れておき、GetResourceStringでリソースを取り
出しtxtファイルに項目毎吐き出します。それでtxtファイルをpdfにしたらまとめる。
ついでにVersion毎の関数も1つのtxtファイルにしておき、検索しながら...っていう感
じで作りました。
こうやれば1日程度で出来ます...、ただ2、3日考えましたが。


Re2: JW取り出しについて     与太郎
email:  Sat Nov 13 14:01:53 2004

以前自作しようと思ってファイル形式の情報を探したのですが、結局見つけられません
でした。でも、バイナリ形式で単精度浮動小数点データを書き出さないといけないとし
たら、VSでは難しいですね。どちらかといえばSDK向きでしょうか。VSだと破線間隔を
得る方法がないのもネックです。
その辺をクリアすれば、書き出す図形の種類は直線、円弧、文字くらいなので、不可能
ではないと思いましたが。


Re5:マニュアルについて   与太郎
email:  Sat Nov 13 13:56:22 2004

石男さん、毎度ありがとうございます。m(_._)m
このPDFの大元は、与太郎が使ったのとおなじものかも。

>使い慣れたExcelで作ってみます
ひとつの関数がExcelの1行に収まるようにしたら、セル内で改行してるので、テンプ
レートがうまく選択できないPDFになってしまいました(セル内の複数行をいっしょに
選択できない、隣のセルの同じ行が選択範囲になる)。単語の途中に改行があると、そ
の語も検索も完全ではないし。これはExcelのままか、印刷して使ったほうがよさそう。

あと、PDFマニュアルってA4縦のレイアウトが多いのですが、画面で見るときは(モニ
タが1024x768だと)都合が悪いので、A4横にしています。


Re4:マニュアルについて   石男
email:  Fri Nov 12 12:59:52 2004

>スクリプト・エディタの関数/手続きの一覧みたいなものがPDF
を作ってみました、各関数の初出バージョン付きです。一応、カテゴリ分けもしてあり
ます。以下のところからDLしてください。各自の判断でお使いください。
http://ric.shokokai.or.jp/tochigi/Html/0940710086/index.htm
なお、Macでのみ確認しています。


Re.: JW取り出しについて   石男
email:  Wed Nov 10 13:42:45 2004

>JW取り出し
は日本仕様でしょうから、カスタマイズは無理です。基本的に「××××取り出し」は
VSのみでの制御は不可です。AppleScriptを併用しないと制御は出来ません。
今のところVWにVisualBasicが対応していませんのでWinでは無理です。
となると、自力でJWが読めるファイルを作る...ってなりますが。現実的ではないで
しょう...。


JW取り出しについて  fuku
email:  Wed Nov 10 7:52:27 2004

はじめてスクリプトを勉強しようと思うのですが、
JW取り出しコマンドをカスタムできるものでしょうか?
具体的に、、
@取り出しについての各変換設定(色・線種等)を保存できるようにする。
AVW側図形の色(寸法・文字含む)をそのまま変換できるようにする。
、、上記の事はできそうでしょうか?
よろしければどなたか道筋があれば教えてもらいたく書き込みました。
どこから手をつけてよいものか、、、困った今日この頃です。


Re3:マニュアルについて   与太郎
email:  Tue Nov 2 22:53:08 2004

>html にして、ついでにテスト結果や、気が付いた事を追加して使っています。
マニュアルが上書き可能なら、そういう使い方も出来ますね。
使い慣れたExcelで作ってみます。


Re^2:マニュアルについて   石男
email:  Mon Nov 1 18:28:46 2004

PDFレフェレンスは日本仕様だったため、今後は出てこない可能性がありますよ。
わたしも皆さん同様にhtml〜PDFに変換したりしていましたが、もう最近はあきらめて
htmlでやっています。しかも、翻訳を当てにしないで原文の方で...。


RE:マニュアルについて  masafumi
email:  Sun Oct 31 0:52:05 2004

同感です。今のマニュアルは関数の内容が理解できていなければ、とても利用できません。
私は個別に分けられた html の Rederence を全て合体して1つの html にして、ついでにテスト
結果や、気が付いた事を追加して使っています。
編集に手間がかかり、ファイル容量は 2.43MB と大きくなりましたが「こんな事ができないか?」
ってな時に、以前のように簡単に単語で検索が出来てとても便利です。
でも、検索する時に間違えて「編集」→「すべて選択」と実行した時は大変です。すべて選択する
まで数分間待たされます(泣)。
また、バージョンアップの度に新規に増えた関数分を編集(合体)しなければならないので、
これも苦の種です。

エーアンドエーさん、全体から検索できる機能をつけて下さい。それが出来なければもとのリファ
レンスに戻してください。お願いします。


マニュアルについて   与太郎
email:  Sat Oct 30 20:48:19 2004

VW9.5までのVS ReferenceマニュアルはPDFなので、OS10.3のPreviewで快適に
検索できて良いのですが、VW10からはhtmlマニュアルしかありません。
htmlマニュアルって、ファイルがカテゴリー別に分かれてるので、
マニュアル全体から単語を検索できなくて不便です。
それで、htmlマニュアルをPDF化できないかと、春ごろから暇をみては作って
いたんですが、いつの間にか忘れてました。それを先日あらためて見たら、
改行位置が変だし、文字サイズがばらばらで、見栄えが良くなかったです。
(ページ数も無駄に多かったし...)

詳しい説明はいらないから、もっとコンパクトなマニュアル(というか関数/
手続きの一覧)を、A&Aで作ってもらえれば一番なんですが。
スクリプト・エディタの関数/手続きの一覧みたいなものがPDFになっていれ
ばいいんです。どのバージョンに対応してるかの情報も付いてたら助かります。
VW11に付いてるということはありませんよね?


RE:タブ区切りファイルについて   与太郎
email:  Thu Oct 14 22:28:36 2004

>石男さん、
データの中でカンマ、スペースを使う(かもしれない)ので、タブ区切りに拘っておりますです。

>masafumiさん、
私も意外でした。思い付く限り、最も簡単で早い方法とは思ってましたが。(^O^)V
条件を同等にするために、関数呼び出しにしてみましたが、ほとんど同じ結果でした。


RE:タブ区切りファイルについて   石男
email:  Thu Oct 14 18:16:25 2004

>タブ区切りファイルの Read、ReadLn でトラブってしまいました。
私も経験ありです、結局タブ区切りをやめてカンマ区切りに変更していまいました。

>IsPolyClosed() 関数
これはSDKの関数をそのまま利用しているのでかなり違いが出ると思いますよ。


RE:タブ区切りファイルについて  masafumi
email:  Thu Oct 14 16:54:25 2004

下記は IsPolyClosed() 関数と、与太郎さんに教えて頂いた方法で、実行時間を
比較してみました・・・。こんなに差が有るとは・・・。(脱帽! m(_ _)m)


{*********** 多角形の開閉チェック(その1) **********}
procedure IsPolyClosed_Test;
var
i :Integer;
objH :Handle;
closeFlg :Boolean;
tick1,tick2:Longint;
ret :Longint;
msg :String;
begin
tick1:=GetTickCount;
for i:=1 to 2000 do
begin
closeFlg:=True;
objH:=FSActLayer;
ret:=GetFPat(objH);
SetFPat(objH, 0);
if (HArea(objH)=0) then closeFlg:=False;
SetFPat(objH, ret);
end;
tick2:=GetTickCount;
msg:=Concat('時間= ',(tick2-tick1));
AlrtDialog(msg);
end;
run(IsPolyClosed_Test);


{*********** 多角形の開閉チェック(その2) **********}
procedure IsPolyClosed_Test;
var
i :Integer;
objH :Handle;
closeFlg :Boolean;
tick1,tick2:Longint;
msg :String;
begin
tick1:=GetTickCount;
for i:=1 to 2000 do
begin
objH:=FSActLayer;
closeFlg:=IsPolyClosed(objH);
end;
tick2:=GetTickCount;
msg:=Concat('時間= ',(tick2-tick1));
AlrtDialog(msg);
end;
run(IsPolyClosed_Test);


タブ区切りファイルについて   与太郎
email:  Thu Oct 14 12:48:06 2004

性懲りもなく、タブ区切りファイルの Read、ReadLn でトラブってしまいました。
少々手を抜こうとしたら、余計に時間がかかったという、最悪のパターンです。
Read、ReadLn が、文字列の先頭のスペースを無視してしまうのが原因だったのですが...

「文字列1+タブ+空白+文字列2」の行を読み込んだ場合、
文字列1 と スペース+文字列2 を取得したいのですが、 タブ+スペース を一つのセパレータと認識するので、
文字列1 と 文字列2 が返ってきます。

また、「文字列1+タブ+タブ+文字列3」を読ませて、文字列1、文字列2(ヌル)、文字列3 を得るつもりでも、
2つのタブが一つのセパレータとなるので、途中で読み込む順番がずれてしまうことも判りました。

行ごとにデータの数が違ってたり、途中に空白データがあったり、スペースで始まる文字列データを含んだ
タブ区切りファイルは、Read、ReadLnでは無理があるようです。
以前書き込んだように、StdReadlnで一行全部読み込んで、自分でタブごとに分割する必要があります。
Read、ReadLn の仕様を理解せずに使ったため、余計な苦労をしてしまいました。マニュアルに詳しく書いて
あれば良かったのですが...。

>masafumiさん、
多角形の開閉状態は、SetFPat(h, 0); A:=HArea(h);で面積を調べれば判ります。
図形のロック状態は、GetBBox()で座標を調べて、HMove()の後の座標と比べてみれば判ります。
どちらも調べた後、最初の状態に戻しまときます。
こんな関数は標準で用意してよ、って思います。あと、レイヤが2D表示か3D表示かを調べる関数も。

ところで、
メッシュ図形の頂点の図形タイプ番号が定義されてるのですが、頂点のハンドルを取得して、座標を調べたり、
頂点を移動したり出来るのでしょうか?


Re6:イベント実行   石男
email:  Fri Oct 8 12:34:05 2004

>IsPolyClosed(polyHandle: HANDLE) : BOOLEAN;
これってかなり前からあります、実は...。
これらの外部関数はNNAのMLにでも質問しないかぎり説明は出ない気がします。


Re5:イベント実行  masafumi
email:  Thu Oct 7 23:30:34 2004

>VWPluginLibraryRoutines.p

こんな関数も有るんですね。

IsPolyClosed(polyHandle: HANDLE) : BOOLEAN;

ポリラインの開閉状態を知ることができる関数のようです。(^_^)v


Re4:イベント実行   与太郎
email:  Thu Oct 7 22:34:39 2004

変更日時順で表示させると、一番上にありました。 > VWPluginLibraryRoutines.p
でも、VW起動or終了のたびに更新されてるようで、不思議です。

>さらにvst...なんたらかんたらと言ったものまで...これはわかりません。
NNAが説明出すまでお預けということですね。社内(NNA)用の関数なのかもしれません。

ところで、
古いスクリプト(8.5用)を10.5で使おうとしたら、思ったとおりに動かず、半日悩んでしまいました。
GetClassOptionsの戻り値が変更されてるのが原因でした。(8.5→9で変更)エラーが出ないので,原
因を見つけるのが大変でした。
定数を外部参照ファイルにして、{$INCLUDE XXX.vss}で参照すれば、バージョンの違いに対処しやすい
と思いますが、エラーが出てうまくいきません。で、結局スクリプト本体に直接書いちゃうんですよね。


Re2:イベント実行   石男
email:  Wed Oct 6 12:49:44 2004

Plug-Insフォルダ内にあるVWPluginLibraryRoutines.p(スペル違いの時はご容赦)を
ご覧下さい。テキストエディタで開けます。
ネメチェック、A+Aの隠しVSが登録されています。これを見ると10.5にはvso...といっ
た一連のものはないんですよ。11にはありますが、さらにvst...なんたらかんたらと
言ったものまで...これはわかりません。

>(大層面倒そうだけど)
結構、凝ると面倒です。ただ新機能のサンプルが全然ないし資料もないので...。


Re2:イベント実行   与太郎
email:  Tue Oct 5 18:12:27 2004

やっぱり10.5では無理でしたね。>「PIOのデータパレットにプッシュボタンを付ける」
VW10.5にはPIOでイベントを受け取るオプションはあるのに(機能はしてないのかも知れませんが)、
イベントを受け取る関数がありません。だから出来ないということです。
VW11のVSRefマニュアルにも、SetObjPropVS、VSOGetEventInfo、VSOAppendWidget、VSOInsertWidget、
VSOInsertAllParams等の項目はありませんが、VW11ではそれらの関数はちゃんと使えるんですよね。
追加機能だからマニュアルにないのでしょうか。
そういえば、HiBaseの関数も、マニュアルに載ってませんけど。(一度どこかで見たはずですが...)

仕方がないのでVW11デモ版で試したら、ちゃんと動きました。感想はというと...
ボタンを付けることよりも、ボタンを押して出てくるもの(モダンダイアログに貼り付けたパターン
選択メニュー)のほうに目が行ってしまいました。
モダンダイアログは使ったことがありませんが、色々面白いことが出来そうなので、勉強してみよう
かな。(大層面倒そうだけど)


Re:イベント実行   与太郎
email:  Fri Sep 24 21:58:49 2004

石男さん、早速ありがとうございます。

眺めましたところ、英語の説明もなんとかならないこともなさそうです。V(^O^)V
これからじっくりと読んでみます。

>書き込んだら長いし、読みづらいですね、
サンプルコードは自分で字下げしながら読みますので、大丈夫です。
長いのは...しかたないですよね。


長文につき...   石男
email:  Fri Sep 24 9:18:15 2004

書き込んだら長いし、読みづらいですね、すみません。
サンプルはProcedure EventEnabledObject;からです。


イベント実行   石男
email:  Fri Sep 24 9:13:16 2004

以下のものは11以降で...、PIOはポイント型で「指定されたイベントで実行」をオンに
してお使いください。
前半はネメチェックが作ったPluginLibraryについての説明です。後半はそれのサンプ
ルです。

{
This file contains the constants necessary to implement extended
properties and events for VectorScript objects. Listed below are the
properties that can be assigned to objects that have the "Script Execution
with Script-Specified Events" set. The object script for an event driven
object must first call the drop-in routine VSOGetEventInfo so the appropriate
event handling code can be called.
}


{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ //\\}
{ //\\ PROPERTY CONSTANTS //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}

{
Extended Properties are set using the drop-in routines SetObjPropVS and
SetObjPropCharVS


kObjXPropEditGroup = 1;
This 8 bit 'Char' property holds one of the property values listed
below in the 'kObjXPropEditGroup Object Property Values' section.


kObjXPropSpecialEdit = 3;
This 'Char' property holds one of the property values listed below in the
'kObjXPropSpecialEdit Object Property Values' section.


kObjXPropPreference = 4;
This 'Boolean property specifies that the object will be called
with its associated event kOnObjPrefEventID. THe object handles
this event by running a custom preferences dialog.


kObjectHasUIOverrideID= 8;
This 'Boolean property specifies that the object will supply widgets
that do not map to parameters. They can provide button widgets as well
as static text using VSOInsertWidget and VSO AppendWidget. Button widgets
also have the associated object event kOnObjectUIButtonHit. The application
calls the object when the user presses the button.
}



{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ 8 bit "Char' / 'Byte' //\\}
{ //\\ //\\}
{ //\\ PROPERTIY VALUES //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}

{ kObjXPropEditGroup Object Property Values
kObjXPropEditGroupDefault = 0;
kObjXPropEditGroupProfile = 1;
kObjXPropEditGroupPath = 2;
kObjXPropEditGroupCustom = 3;}

{ kObjXPropSpecialEdit Object Property Values
kDefaultSpecialEdit = 0;
kCustomSpecialEdit = 1;
kPropertiesSpecialEdit = 2;
kReshapeSpecialEdit = 3;}


{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ Object Definition Procedure //\\}
{ //\\ //\\}
{ //\\ EVENT IDs //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{
kResetEventID= 3;
The state of the object has changed and the application
calls the script to regenerate itself. The application has set
the VectorScript environment so all objects creation goes into
the object container with appropriate defaults.


kOnObjPrefEventID= 4;
The object is being inserted in a drawing for the first time
or the preferences button has been pressed in the objects insertion
tool. Objects with the kObjXPropPreference property set use
this event to supply a custom dialog to edit object defaults.


kObjOnInitXProperties= 5;
kOnInitPropertiesEventID= 5; an earlier naming of the above -- needs to be removed
The Application needs to know what extended properties are present
for this object. It calls the script with a kObjOnInitXProperties
so the script can supply these properties.


kObjOnSpecialEditID= 7;
Objects that have specified a kObjXPropSpecialEdit property value
of kCustomSpecialEdit are called by the application when the user
invokes the Special Edit command from the context menu or from a
cursor tool double-click.


kOnObjectUIButtonHit= 35;
Objects that have specified a kObjectHasUIOverrideID property and
have added a button widget are called with this event when the user
presses the specified button. Scripts use the eventData and the
script supplied mappingID to distinguish between multiple buttons.
Buttons should be used to edit object properties NOT to execute a command.
For example, an object should not supply a button that operates on any
property that does not belong to this object instance.
}



{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ kObjectHasUIOverrideID //\\}
{ //\\ //\\}
{ //\\ Widgets Constants //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{

kFieldLongInt= 1;
kFieldBoolean= 2;
kFieldReal= 3;
kFieldText= 4;
kFieldCalculation= 5;
kFieldHandle = 6;
kFieldCoordDisp= 7; dimension
kFieldPopUp= 8;
kFieldRadio= 9;
kFieldCoordLocX= 10;
kFieldCoordLocY= 11;

kWidgetButton= 12;
kWidgetStaticText= 13;
kWidgetDisclosure= 14; not implemented?}


{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\ //\\}
{ //\\ Extended Object Properties //\\}
{ //\\ //\\}
{ //\\ Drop-in APIs //\\}
{ //\\ //\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}
{ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\}

{

SetObjPropVS(propertyID: LONGINT;
propertyVal: BOOLEAN)
: BOOLEAN;
SetObjPropVS is called from the kObjOnInitXProperties event handling code to
supply boolean properties.


SetObjPropCharVS(propertyID: LONGINT;
propertyVal: CHAR)
: BOOLEAN;
SetObjPropCharVS is called from the kObjOnInitXProperties event handling code to
supply 8 bit Char/Byte properties.

VSOGetEventInfo(VAR outObjEvent: LONGINT; // the current event
VAR outEventData: LONGINT);// the current event data
Event handling scripts always call VSOGetEventInfo to get the current event.

VSOAppendWidget(widgetType: LONGINT; // kWidgetButton or kStaticText
mappingID: LONGINT; // script supplied ID returned supplied with
text: STRING; // The text of the widget
data: LONGINT) // unused
: BOOLEAN;
Objects that have set the kObjectHasUIOverrideID property call VSOAppendWidget to
add specified widget to the current widget list.

VSOInsertWidget(paramID: LONGINT; // the index of the parameter after this widget
widgetType: LONGINT; // kWidgetButton or kStaticText
mappingID: LONGINT; // object supplied ID returned supplied with
// kOnObjectUIButtonHit
text: STRING; // The text of the widget
data: LONGINT) // unused
: BOOLEAN;
Objects that have set the kObjectHasUIOverrideID property call VSOInsertWidget
to specify a widget in the shape pane and properties dialog. See the Widgets Constants
above for suppoerted widgetType. The Mapping Id is returned in the outEventData
parameter of VSOGetEventInfo during kOnObjectUIButtonHit events.

VSOInsertAllParams() : BOOLEAN;
Objects that have set the kObjectHasUIOverrideID property call VSOInsertAllParams
to insert all the parameter widgets defined FOR the OBJECT.}

Procedure EventEnabledObject;
Const
kOnInitPropertiesEventID = 5 ;
kOnObjPrefEventID= 4 ;
kWidgetButton = 12 ;
kObjectHasUIOverrideID = 8 ;
kResetEventID = 3 ;
kOnObjectUIButtonHit = 35 ;
Var
theEvent, theButton : Longint ;
objHand, recHand, wallHand : Handle ;
objName, saveClass, noneClass : String ;
fillPattern :integer;
cnt : Integer ;
int : Integer ;
boo : Boolean ;
str : String ;


Procedure dialog1_Main( Var fillPattern : Integer ) ;
Var
dialog1 : Integer ;
imagePopup4Int : Integer ;

Procedure LoadPatterns( dialogID , controlID : Longint ) ;
Var
garbInt : Integer ;
Begin
If GetObject('System: Pattern Previews') = nil Then Begin
NameObject('System: Pattern Previews');
BeginFolder;
EndFolder;
End ;
If GetObject('Pattern-00') = nil Then Begin
BeginSym(Concat('Pattern-00', str));
Rect(0, 0, 10, 10); SetFPat(LNewObj, 0); SetLW(LNewObj, 1); SetPenFore(LNewObj, 0, 0, 0);
MoveTo(0, 0); LineTo(10, 10); SetLW(LNewObj, 1); SetPenFore(LNewObj, 0, 0, 0);
MoveTo(10, 0); LineTo(0, 10); SetLW(LNewObj, 1); SetPenFore(LNewObj, 0, 0, 0);
EndSym;
InsertSymbolInFolder(GetObject('System: Pattern Previews'), GetObject('Pattern-00'));
For cnt := 1 to 71 Do Begin
str := Num2Str(0, cnt);
If Len(str) = 1 Then str := Concat('0', str);
BeginSym(Concat('Pattern-', str));
Rect(0, 0, 10, 10);
SetFPat(LNewObj, cnt);
SetLW(LNewObj, 1);
SetPenFore(LNewObj, 0, 0, 0);
EndSym;
InsertSymbolInFolder(GetObject('System: Pattern Previews'), GetObject(Concat('Pattern-', str)));
End ;
End ;
RemoveAllImagePopupItems(dialogID, controlID);
For cnt := 0 to 71 Do Begin
str := Num2Str(0, cnt);
If Len(str) = 1 Then str := Concat('0', str);
garbInt := InsertImagePopupObjectItem(dialogID, controlID, Concat('Pattern-', str));
End ;
SetImagePopupSelectedItem(dialogID, controlID, 1);
End ;


Procedure dialog1_Handler( Var item : Longint ; data : Longint ) ;
Begin
Case item of
SetupDialogC :
Begin
LoadPatterns(dialog1, 4);
SetImagePopupSelectedItem(dialog1, 4, fillPattern + 1);
End ;
1: Begin
imagePopup4Int := GetImagePopupSelectedItem(dialog1, 4);
End ;
End ;
End ;

Begin
dialog1 := CreateLayout('Select A Pattern', FALSE, 'OK', '');
CreateControl(dialog1, 4, 10, '', 0);
SetFirstLayoutItem(dialog1, 4);
If RunLayoutDialog(dialog1, dialog1_Handler) = 1 Then fillPattern := imagePopup4Int - 1;
End ;


Procedure ResetEventHandler;
Begin
Rect(0, 0, 1, 1);
SetFPat(LNewObj, pPattern_Number);
End ;

{=================Main===================}
Begin
vsoGetEventInfo(theEvent, theButton);
Message( 'theEvent= ' , theEvent , ' theButton= ' , theButton ) ;
Case theEvent of
kOnInitPropertiesEventID:
Begin
boo := SetObjPropVS(kObjectHasUIOverrideID, TRUE);
boo := vsoInsertAllParams;
boo := vsoAppendWidget(kWidgetButton, 1, 'Select Pattern...', 1);
boo := vsoAppendWidget(kWidgetButton, 2, 'Add...', 1);
End ;
kOnObjectUIButtonHit:
Begin
Case theButton of
1 : Begin
boo := GetCustomObjectInfo(objName, objHand, recHand, wallHand);
fillPattern := Str2Num(GetRField(objHand, objName, 'Pattern Number'));
dialog1_Main(fillPattern);
SetRField(objHand, objName, 'Pattern Number', Num2Str(0, fillPattern));
ResetObject(objHand);
End ;
2 :Begin
End ;
End ;
End ;
kResetEventID:
Begin
ResetEventHandler;
End ;
End ;
End ;
Run(EventEnabledObject);




Re:スクリプトの中で線種選択メニューを使う   与太郎
email:  Thu Sep 23 20:02:39 2004

下のprocedureでグループ図形を触ると、グループ内の図形の面の色が変わってしまいます。
このままでは危なくて使えません。
グループの属性を変えると、その中の全ての図形の属性も変わってしまうのですね。
いままで、グループ内の個々の図形にアクセスしないといけないと思ってました。


スクリプトの中で線種選択メニューを使う   与太郎
email:  Thu Sep 23 12:37:19 2004

メニューで線種を選択して、線種番号を返すprocedureです。
メニュー外の図形でも選択できてしまいますが、ハンドルをチェックして、
選択しないように修正可能です。

procedure Test_LineStyle;
var
_lnStyle_:integer;
_
procedure GetLineStyle(var lS:integer);
{ メニューで線種を選択して、線種番号を返します。 }
{ 注意:環境設定の「VectorScriptの警告を表示」を強制的にOFFにしています。 }
const
_LineLength = 150;
_Pitch = 16;
_FlipCol = 18;
var
_hL, hR_:array[-32..2] of handle;
_h, h0_:handle;
_i_:integer;
_xc, yc, zoom_:real;
_x0, y0, lnLen_:real;
_showLnWt_:boolean;{ 拡大時に線の太さを表示 }
_x, y, k_:real;
_minLnStyle_:integer;{ 線種番号の下限 }
_lnStyle_:integer;{ デフォルトの線種 }
_r, g, b_:real;
_ff, fb_:integer;
_
_function Set_k:real;{ 描画倍率を計算します。 }
_var
__scale, upi_:real;
__fraction, display_:longint;
__format_:integer;
__name, squareName_:string;
_begin
__scale:= GetLScale(ActLayer);
__GetUnits(fraction, display, format, upi, name, squareName);
__Set_k:= upi * scale / 25.4 / 72 * 25.4;
_end;{Set_k}

begin{GetLineStyle}
_SetPref(21, false);
_lnStyle:= FPenPat;
_i:= 0;
_repeat{ 線種の数(線種番号の下限)を調査します。 }
__i:= i - 1;
__PenPat(i);
_until FndError;
_minLnStyle:= i + 1;
_showLnWt:= GetPref(9);
_SetPref(9, false);
_GetVCenter(xc, yc);
_zoom:= GetZoom;
_SetZoom(100);
_k:= Set_k;
_lnLen:= k * LineLength;
_x0:= xc - lnLen/2;
_y0:= yc - k*minLnStyle*Pitch/2;
_y:= y0;
_for i:= 2 downto minLnStyle do begin{ メニュー項目描画ループ }
__if (i = 2) | (i < 0)then begin
___PenPat(i);
___Rect(x0-k*Pitch, y+k*Pitch/2, x0+lnLen+k*Pitch, y-k*Pitch/2);
___hR[i]:= LNewObj;
___SetDSelect(hR[i]);
___SetFPat(hR[i], 2);
___SetLW(hR[i], 0);
___SetFillFore(hR[i], 0);
___MoveTo(x0, y); LineTo(x0 + lnLen, y);
___hL[i]:= LNewObj;
___SetDSelect(hL[i]);
___y:= y - k*Pitch;
__end;{if}
_end;{for}
_PenPat(2);
_Rect(x0-k*Pitch, y0+k*Pitch/2, x0+lnLen+k*Pitch, y0-k*Pitch*(1/2-minLnStyle));{ メニュー枠 }
_hL[0]:= LNewObj;
_SetFPat(hL[0], 0);
_SetFillFore(hL[0], 0);
_SetDSelect(hL[0]);
_ReDrawAll;
_h0:= nil;
_ff:= 0;
_fb:= 0;
_while not MouseDown(x, y) do begin{ メニュー項目選択ループ }
__GetMouse(x, y);
__h:= PickObject(x, y);
__for i:= 2 downto minLnStyle do
___if (h <> nil) & (h = hL[i]) then
____h:= hR[i];
__if h <> h0 then begin
___if h0 <> nil then begin
____SetFillFore(h0, ff);
____SetFillBack(h0, fb);
___end;{if}
___GetFillFore(h, r, g, b);
___RGBToColorIndex(r, g, b, ff);
___GetFillBack(h, r, g, b);
___RGBToColorIndex(r, g, b, fb);
___SetFillFore(h, FlipCol);
___SetFillBack(h, FlipCol);
___h0:= h;
___ReDrawAll;
__end;{if}
_end;{while}
_SetFillFore(h0, ff);
_SetFillBack(h0, fb);
_if h = nil then begin
__lS:= 2;
_end{if}
_else begin
__lS:= GetLS(h);
_end;{else}
_for i:= -32 to 2 do begin{ メニュー項目削除ループ }
__if hL[i] <> nil then
___DelObject(hL[i]);
__if hR[i] <> nil then
___DelObject(hR[i]);
_end;{for}
_SetZoom(zoom);
_SetPref(9, showLnWt);
_PenPat(lnStyle);
_ReDraw;
end;{GetLineStyle}

begin{main}
_GetLineStyle(lnStyle);
_Message('LineStyle= ', lnStyle);
end;
Run(Test_LineStyle);


ポイント型のPIOにプッシュボタンを付ける方法   与太郎
email:  Wed Sep 22 20:52:58 2004

石男さん、要望します、お願いします、披露してくださいませ。m(_._)m
(急ぎませんので、HiBaseが終わってからでかまいませんよ。)

VS Language Guide(11) の第10章の Setting Script Execution Options の、
With Script-Specified Events 項目が関係ありとみましたが、間違ってますか?
そこから先へは進めませんでしたが。


Re:スクリプトの中でカラーパレットを使う   与太郎
email:  Wed Sep 22 20:19:25 2004

>ちょっと変えれば色番号や線種を選択するサブルーチンも出来そうです。
ちょっと変えれば模様番号や線種を選択するサブルーチンも出来そうです。
の間違いでした。

白黒表示やカラーレイヤ表示のときは色が判りませんが、一時的にカラー表示に変更すれば、
大丈夫でしょう。
あと、線種を表示するときは、「拡大時に線の太さを表示」させないとか。


Re.無題   石男
email:  Wed Sep 22 8:37:34 2004

与太郎さん
厳密に言えば10.5からいけるはずなんですが、どうも駄目でした。で私的に確認したの
は11ということで...。
そう!バリバリの英語です。要望があればここに出しますが...。


スクリプトの中でカラーパレットを使う   与太郎
email:  Tue Sep 21 22:09:40 2004

とりあえず使う予定はないんですが、色を選択するprocedureを作ってみました。
procedure GetColIndex がそれです。
ちょっと変えれば色番号や線種を選択するサブルーチンも出来そうです。

procedure Test_ColorPalett;
var
_col_:integer;

procedure GetColIndex(var iCol:integer);
{ カラーパレットを表示して、色番号を返します。 }
{ キャンセル(範囲外)なら-1を返します。 }
const
_BlockSize = 18;
var
_zoom, xc, yc_:real;
_k, kB, kS_:real;
_x, y, x0, y0_:real;
_i, j_:integer;
_h _:handle;
_hB_:array[0..15, 0..15] of handle;
_r, g, b_:real;
_
_function Set_k:real;{ 描画倍率を計算します。 }
_var
__scale, upi_:real;
__fraction, display_:longint;
__format_:integer;
__name, squareName_:string;
__result_:real;
_begin
__scale:= GetLScale(ActLayer);
__GetUnits(fraction, display, format, upi, name, squareName);
__Set_k:= upi * scale / 25.4 / 72 * 25.4;
_end;{Set_k}
_
_function LocToColIndex(iX, iY:integer):integer;
_var
__result_:integer;
__i_:integer;
_begin
__i:= 16 * iY + iX;
__case i of
___1: result:= 255;
___17: result:= 254;
___22: result:= 247;
___23: result:= 252;
___25: result:= 253;
___29: result:= 249;
___34: result:= 251;
___37: result:= 246;
___43: result:= 250;
___45: result:= 245;
___47: result:= 248;
___245: result:= 45;
___246: result:= 37;
___247: result:= 22;
___248: result:= 47;
___249: result:= 29;
___250: result:= 43;
___251: result:= 34;
___252: result:= 23;
___253: result:= 25;
___254: result:= 17;
___255: result:= 1;
___otherwise result:= i;
__end;{case}
__LocToColIndex:= result;
_end;{LocToColIndex}
_
begin{GetColIndex}
_k:= Set_k;
_GetVCenter(xc, yc);
_zoom:= GetZoom;
_kB:= k * BlockSize * 100 / zoom;
_kS:= kB / 6;
_x0:= xc - 8 * kB;
_y0:= yc + 8 * kB;
_for j:= 0 to 15 do begin
__for i:= 0 to 15 do begin
___Rect(x0+i*kB+kS, y0-j*kB-kS, x0+(i+1)*kB-kS, y0-(j+1)*kB+kS);
___hB[i, j]:= LNewObj;
___SetDSelect(hB[i, j]);
___SetFPat(hB[i, j], 2);
___SetFillFore(hB[i, j], LocToColIndex(i, j));
__end;{for}
_end;{for}
_ReDraw;
_i:= -1; j:= -1;
_GetPt(x, y);
_h:=PickObject(x, y);
_if h = nil then begin
__iCol:= -1;
_end{if}
_else begin
__GetFillFore(h, r, g, b);
__RGBToColorIndex(r, g, b, iCol);
_end;{else}
_for j:= 0 to 15 do
__for i:= 0 to 15 do
___DelObject(hB[i, j]);
end;{GetColIndex}

begin{main}
_GetColIndex(col);
_Message(col);
end;
Run(Test_ColorPalett);


Re2: 無題   与太郎
email:  Tue Sep 21 22:07:20 2004

>石男さん
英語ですか〜、VW11ですか〜(泣き)。

やっぱりバージョンアップするべきか。
バグが出尽くすまで待ってみようかと思ってましたが、
これって、早めにバージョンアップor新規購入した人にテストしていただいているということですよね。


Re: 無題   石男
email:  Fri Sep 17 14:51:24 2004

>ポイント型のPIOにプッシュボタンを付ける
 ネメチェックのVSマニュアルを読むとPIOにイベントが付けられます。実際には11か
らの機能ですが、これを使ってPIOのデータパレットにプッシュボタンが付けられす。
普通、PIOにはダイアログが付けられませんが、プッシュボタンに仕込むことが出来ま
す。後はSetRFieldを使ってダイアログからの贈り物をセットしていくだけです。
 でも、サンプルはネメチェックのVS_MLの過去のログに埋没しています。当然ながら
全て英文で書かれています。


無題   与太郎
email:  Fri Sep 17 12:59:09 2004

石男さん、
>与太郎さんのつっこみにはたじたじです...。
ほっとくと段々増長してきますが、注意していただけたら静かになると思います。

>ポイント型のPIOにプッシュボタンを付ける
イメージできませんでした。
オブジェクトにボタンが付いてるのですか?
ボタンを押したらイベントを送れるのですか?
どうやってイベントを受け取るのですか?
勉強会が終わって暇が出来たら、教えてくださいな。
って、ぜんぜん静かになってませんねえ。

最近、Contorol Pointというもパラメータのを発見(見逃してただけ)したので、1点、2点、3点型
のPIOでも制御点を増やせることがわかって喜んでおります。2Dパスでやると、変形時に余計な線が
表示されて見苦しいし、文字を自分で回転させないといけないので、ちょっと悩んでおりました。
Contorol Pointはデータパレットで表示されなくても困らないので、パラメータの下のほうにして
おけばデータパレットの表示領域を圧迫しないのもいいですね。

PIOのパラメータをプラグインの中で書き換える必要があって、バックナンバーを読んでみましたが、
ソースがなかったので,わかりにくかったです。レコードハンドルと図形ハンドルを混同して、一時
間ほど原因を探してしまいました。
ポップアップ型のパラメータで、リストにないサイズをダイアログで入力するルーチンです。
「直接入力...」の項目を選択すると、ダイアログが出るというものです。値が「直接入力...」のま
まだとオブジェクトを変更するたびにダイアログが出るので、書き換える必要がありました。


HiBaseのことなど...   石男
email:  Wed Sep 15 9:00:16 2004

与太郎さんのつっこみにはたじたじです...。

HiBaseに関しては、マニュアルにある通りの使い方しかわかりません。したがって、現
状では使いにくいものかもしれません...。それでも、発表されてから石男はずーっと
使い続けています。もっと反応があれば善処してくれるはずです...。

その代わりと言ってはなんですが、モダンダイアログ(カスタム)で条件に応じて
アイテムを作りだす技?やポイント型のPIOにプッシュボタンを付けることなどなら、ご希望にお答えできると思います...。


Re8:レコード付き図形   与太郎
email:  Tue Sep 14 18:50:21 2004

D-Dayまで10日ですね。
外部データベースの使い道、わかりません。(そういう仕事もないし)
でも、興味があるので、(東京クラブの勉強会だけど、)ここで発表していただけたらいいなあ。
あるいは、「From A&A」とかでね。

標準Pascalの IN [ ] ていうのは [ ]内は整数型だから、(R IN ['レコード'])のように文字列型が許される
のは変なんですが、内部的にはレコードのインデックス番号みたいなので処理してるのかなと思ってました。
でも違ってました。
実際は、スクリプトを実行するときに検索条件の ( )内の式をインタープリタで処理してるのですね。
よく考えれば、実行してみないとレコードの番号は特定できませんから、当然です。
VW8でインタープリタ方式から(Javaみたいに中間コードを生成する)コンパイラ方式に変更になったけど、
検索条件を評価する部分はインタープリタのままということのようです。
そのこと自体は悪くないんだけど、(R IN [ ])というのが、Pascalの集合型と同じ表現だし、
レイヤーの場合は(L=layerName)と、変数でも指定できるので、勘違いしてしまいました。

ところで、レコード名に「'」が含まれてると、スクリプトで厄介なことになりそうです。


Re7:レコード付き図形   石男
email:  Tue Sep 14 12:57:41 2004

>ところで、もしかして、これってHiBaseに関係あります?
かなり、関係があります...。


Re6:レコード付き図形   与太郎
email:  Mon Sep 13 19:13:06 2004

恐縮です。書き直しですか〜。
思い出すのに半日も掛かかるなんて、カセットテープから(300ボーくらいで)データを読んでるような遅さでした。
ところで、もしかして、これってHiBaseに関係あります?


Re5:レコード付き図形   石男
email:  Mon Sep 13 17:25:22 2004

いや、本当に済みません、与太郎さん。
今、総当たりのScriptを書き終わったところでした...。
もう一度、参考にして書き直します...、与太郎さん。


Re4:レコード付き図形   与太郎
email:  Mon Sep 13 13:54:07 2004

検索条件を文字列にすれば良かったのを思い出しました。

procedure test1;
const
Rec1 = 'Record-1';
Rec2 = 'Record-2';
SQ = Chr(39);
var
criteria:string;
begin
criteria:= Concat('(R IN [', SQ, Rec1, SQ, ', ', SQ, Rec2, SQ, '])');
Message(Count(criteria), ' : ', criteria);
end;
Run(test1);

procedure test2;
const
Rec1 = '''Record-1''';
Rec2 = '''Record-2''';
var
criteria:string;
begin
criteria:= Concat('(R IN [', Rec1, ', ',Rec2, '])');
Message(Count(criteria), ' : ', criteria);
end;
Run(test2);

どちらも同じ結果になります。

>図形タイプに47、48とにレコードが定義されているのが不思議です...。
Type47---レコード定義。シンボルフォルダにリンクされてます。
たぶん、シンボル定義と同じ方法でハンドルを取ります。
Type48---レコード。図形にリンクされてます。GetRecord(objHandle, index)でハンドルを取ります。


Re3:レコード付き図形   石男
email:  Mon Sep 13 12:32:31 2004

いつも、どうもすみません、与太郎さん。
やはり、検索条件に直接レコード名をいれないといけないんですね。
別な手でNameListからやってみましたが、やはりレコードのハンドルは返ってきません
でした...。当然と言えば当然でしたが、そうなるとベタな総当たりで順を追ってやる
方法しかないようですね...。しかし、図形タイプに47、48とにレコードが定義されて
いるのが不思議です...。


Re2:レコード付き図形   与太郎
email:  Mon Sep 13 10:58:34 2004

[ ]内に直接レコード名を入れないとダメみたいです。

procedure test1;
const
Rec1 = 'Record-1';
Rec2 = 'Record-2';
begin
Message(Count((R IN [Rec1, Rec2])));
end;
Run(test1);

procedure test2;
var
rec1, rec2:string;
begin
rec1:= 'Record-1';
rec2:= 'Record-2';
Message(Count((R IN [rec1, rec2])));
end;
Run(test2);

残念ながら、test1、test2共にコンパイルされますが、カウントされませんでした。
(VW10/Winデモ版にて)


Re:レコード付き図形   与太郎
email:  Mon Sep 13 10:18:53 2004

石男さん、
レコードの種類が多いとたいへんですが、
i:= Count(R IN ['Record-1','Record-2']);
でカウント出来ます。
'Record-1'か'Record-2'のどちらかでも付いてればカウントされます。


レコード付き図形   石男
email:  Mon Sep 13 8:55:34 2004

レコード付き図形の数をカウントしようと思って...
i := Count( T = 47 ) ;もしくは T = 48でやってみたところ
「0」しか返ってきません。当然、レコード付き図形はばらまいています。
やはり、図形のハンドルを取ってからレコードの有無を確認するしかないのでしょうか


Re3:重複グループを削除するスクリプト  nao
email:  Mon Sep 13 1:06:27 2004

与太郎さんご親切にありがとうございます。
>うっかり「コマンド+D」を押したり、複製したのに移動するのを忘れたり、3D図形を2D化して、
>図形が重なってしまうのはよくあることです。ワークシートで集計したりするときには、致命的です。
>「不要情報を除去...」に、「重複図形を削除」のオプションがあると助かるのですがね。
同感です。これがあることでどれだけ仕事が短縮されることか。心置きなくワークシートを使える環境が
整うことを願っています。
>Script談話室のバックナンバーに「重複図形を削除」について、一連のやりとりがあります。
拝見しましたが難しすぎてチンプンカンプンです。やはりスクリプトのハードルは高いですね。
(重複グループ図形を削除するスクリプト)で少しずつ勉強してみます。


Re2:重複グループを削除するスクリプト   与太郎
email:  Sun Sep 12 15:40:28 2004

>シンボルを並べて配列のパターンをグループ化していたので
普通、グループでなくてシンボルを並べますよね(でないと修正がたいへん)。一応、シンボル版も作ってみまし
たが、グループ版だけ書き込みました。GROUP→SYMBOL の変更は直感でわかりましたか?

>数百個単位の図形なら同じ図形の重複は下のスクリプトのタイプの部分を変えることでほぼ対応出来る
>のでしょうか?
下のスクリプトは図形のBoundRectを比較しているだけなので、限定された条件でしか正しく動きません。(基本
的に図形が重なることはない、属性を無視できること)
厳密には、直線なら端点同士、多角形なら頂点全部を比較するなど、図形タイプによって、処理の仕方を変えない
といけません。2D図形だと、下のようになります。

基準点----X,Y座標
直線------端点の座標
四角形----BoundRect
多角形----とりあえずBoundRect、そのあと各頂点座標、開/閉
曲線------とりあえずBoundRect、そのあと各頂点座標/タイプ、開/閉、各辺の表示/非表示
円弧------中心座標、半径、開始角、円弧角
円--------中心座標、半径
シンボル--シンボル名、挿入点座標、回転角
グループ--とりあえずBoundRect、そのあと中の図形ごとに比較
文字------基点の座標、角度、反転、文字、フォント,サイズ,スタイル
寸法------基準点座標、オフセット、その他

全ての図形---属性(クラス、線/面の色、パターン、線種、マーカー)、ロック状態

また、図形に名前、レコードが設定されていれば、それも考慮しないといけません。(名前が付いていたら削除し
ないとか、レコードの内容が同じなら削除するとか)

きちんとやると(量的に)たいへんです。

>タイプによってデータが壊れるようなことはないのですか。
きちんと比較しないと、実際には重複していない図形を削除してしまう恐れがあります。

うっかり「コマンド+D」を押したり、複製したのに移動するのを忘れたり、3D図形を2D化して、図形が重なっ
てしまうのはよくあることです。ワークシートで集計したりするときには、致命的です。「不要情報を除去...」に、
「重複図形を削除」のオプションがあると助かるのですがね。

Script談話室のバックナンバーに「重複図形を削除」について、一連のやりとりがあります。


Re:重複グループを削除するスクリプト  
email:  Sun Sep 12 0:35:34 2004

与太郎さんありがとうございます。
説明不足でした。シンボルを並べて配列のパターンをグループ化していたので全て並べた後グループ
を解除することでグループの重複ではなくシンボルが重複していました。
そこで下のスクリプトの(T=GROUP)の部分を(T=SYMBOL)してみたらうまく消えてくれました。

数百個単位の図形なら同じ図形の重複は下のスクリプトのタイプの部分を変えることでほぼ対応出来る
のでしょうか?タイプによってデータが壊れるようなことはないのですか。スクリプトは全然わからず
メニューツールの選択/表示マクロ位しか使っていないのでよくわかりません。
VectorWorks 談話室より
>>3つ重なった図形の見つけ方教えてください  nao  Sat Sep 11 13:37:14 2004
>>レイアウトで300個ほどの図形を配置する仕事がありました。縦横が揃っているわけではなく
>>模様のように並べるとのことでした。パターンを造りグループ化して並べていきました。2つ重なった
>>図形は選択すればわかるのですが3つ重なった図形は1度見逃すと探し出せません。当然造るのに並べた
>>場合の正確な個数が知りたいとのことでしたので結局図面から何回も数え、計算で出したものと比較し
>>て出しました。重なりが怖くてワークシートのCOUNTは使えませんでした。
>>作図後重なった図形を見つける方法がありましたら教えてください。


重複グループを削除するスクリプト   与太郎
email:  Sat Sep 11 16:25:21 2004

アクティブレイヤの重複グループ図形を削除します。外枠の大きさだけ比較しています。
グループの中身はは調べていません。
数百個の図形なら全部比較しても時間はかからないので、図形ハンドルのソートもやってません。
何千個にもなると、このスクリプトでは時間がかかり過ぎるでしょう。

procedure Del_OverlapGroup;{ 重複グループを削除する }
{$ DEBUG}
var
actLName:string;
x11, y11, x12, y12:real;
x21, y21, x22, y22:real;
h1, h2, hD:handle;
i, n, num:integer;
begin
actLName:= GetLName(ActLayer);
DSelectAll;
num:= Count((L=actLName)&(T=GROUP));
SelectObj((L=actLName)&(T=GROUP));
n:= 0;
i:= 0;
h1:= FSActLayer;
while h1 <> nil do begin
i:= i + 1;
Message(Concat(Num2Str(0, n), ' : ', Num2Str(0, i), ' / ', Num2Str(0, num)));
h2:= NextSObj(h1);
while h2 <> nil do begin
GetBBox(h1, x11, y11, x12, y12);
GetBBox(h2, x21, y21, x22, y22);
if EqualRect(x11, y11, x12, y12, x21, y21, x22, y22) then begin
hD:= h2;
h2:= NextSObj(h2);
DelObject(hD);
n:= n + 1;
i:= i + 1;
Message(Concat(Num2Str(0, n), ' : ', Num2Str(0, i), ' / ',

Num2Str(0, num)));
end{if}
else begin
h2:= NextSObj(h2);
end;{else}
end;{while}
h1:= NextSObj(h1);
end;{while}
DSelectAll;
ClrMessage;
if n > 0 then begin
AlrtDialog(Concat(Num2Str(0, n), '個のグループを削除しました。'));
end;{if}
end;
Run(Del_OverlapGroup);


ワークシートの文字を描くスクリプト   与太郎
email:  Wed Sep 8 12:57:50 2004

ワークシートの選択範囲のセルの文字を、クリック−ドラッグで描きます。クリックで終了します。
フォント、サイズ等は実行前に設定しておきます。
VW9以降対応です。

procedure DrawTextFromWS;{ WSの文字を、クリック−ドラッグで描きます }
{ $ DEBUG }
var
_hWS, hTx_:handle;
_row, maxRow,
_clm, maxClm,
_top, left,
_topSub, bottom, right, botSub_:integer;
_x1, y1, x2, y2_:real;
_str_:string;
_vec_:vector;
_ang_:real;
begin
_hWS:= ActSSheet;
_if hWS = nil then begin
__AlrtDialog('ワークシートを開いてください。');
_end{if}
_else begin
__DSelectAll;
__GetWSRowColumnCount(hWS, maxRow, MaxClm);
__GetWSSelection(hWS, row, clm, top, left, topSub, bottom, right, botSub);
__Message('文字を描く位置でクリック−ドラッグしてください。 クリックで終了します。');
__hTx:= nil;
__GetLine(x1, y1, x2, y2);
___if (top = bottom) & (left = right) then begin
____top:= 1; Left:= 1; bottom:= maxRow; right:= maxClm;
____SetWSSelection(hWS, row, clm, top, left, topSub, bottom, right, botSub);
___end;
__while not EqualPt(x1, y1, x2, y2) do begin
___GetWSCellFormula(hWS, row, clm, str);
___clm:= clm + 1;
___if clm > right then begin
____clm:= left;
____row:= row + 1;
____if row >bottom then begin
_____row:= top;
____end;{if}
___end;{if}
___SetWSSelection(hWS, row, clm, top, left, topSub, bottom, right, botSub);
___vec.x:= x2 - x1;
___vec.y:= y2 - y1;
___ang:= Vec2Ang(vec);
___TextOrigin(x1, y1);
___TextRotate(ang);
___CreateText(str);
___DSelectObj(hTx);
___hTx:= LNewObj;
___SetSelect(hTx);
___ReDraw;
___GetLine(x1, y1, x2, y2);
__end;{while}
__ClrMessage;
_end;{else}
end;
Run(DrawTextFromWS);

ちゃんと動くのですが、下のような警告メッセージが出てしまいます。
Warning: DRAWTEXTFROMWS BOTSUB - Attempt to access a cell outside the worksheet bounds.
GetWSSelection()でエラーが出てるようですが、意味がわかりません。
どうしたら警告が出ないように直せるでしょうか?


V ORO
email:  Tue Sep 7 18:43:30 2004

はじめまして、私は今、卒業研究で「Vector Worksで住宅の3Dを作って、Vector
Scriptでデータを取り出す。」という作業をやっています。しかし、初めてVector
Scriptを使うため、よく分かりません。
Vector Worksのなかの壁ツールをつかって、壁をかき、フラッシュ戸という建築ツールを壁にせんにゅうしました。それをVector Scriptでとりだすと、
{Object Creation Code}

NameClass('一般');
SetZVals(0,2400);
DoubLines(200);
ClearCavities;
PenSize(2);
PenPat(2);
FillPat(1);
PenFore(56797,0,0);
PenBack(65535,65535,65535);
Wall(-8888,11111,-8888,7019.37500119);
WallCap(FALSE,FALSE,FALSE,0,0);
AddSystemToWallEdge(LNewObj,1695.812499,0,FALSE,FALSE,'フラッシュ戸',0);
WallCap(TRUE,FALSE,FALSE,100,-100);
SetZVals(0,0);

{End of Creation Code}
というのがでてきて、この部分がオブジェクトのデータだと思うんですが、
WallCapとAddSymToWallEdgeの部分の数値とTRUE,FALSEが何を表しているのか分か
りません。
どなたか教えていただけませんか??




わざわざどうもです   石男
email:  Mon Sep 6 18:14:21 2004

与太郎さん
わざわざの解説ありがとうございます。なるほど、合点がいきました。
しかも、WS_to_GroupObj改訂版まで...、感謝にたえません。


WS_to_GroupObjについて & WS_to_GroupObj改訂版   与太郎
email:  Mon Sep 6 15:32:56 2004

石男さん、

>以前、与太郎さんが提供してくれたWSをグループ図形に変換するおまじないについて
>質問なのですが、サブルーチンのDrawGridとDrawHBorders、DrawVBordersは何か
>違いがあるのですか?

DrawGrid--------グリッド(セルの境界全部)に線を引きます。
DrawHBorders----横方向の枠線を引きます。
DrawVBorders----縦方向の枠線を引きます。
(グリッドは、WSメニューの「レイアウト設定...」で表示/非表示を設定します。)
(枠線は、WSメニューの「枠線...」で設定します)

ついでに、データベースの従属行を表示出来るように修正したのも出しときます。
2種類の行番号(従属行を含むのと、含まないの)が出てくるので、判りにくくなっちゃいました。

procedure WS_to_GroupObj;
{ Version 0.99 }
{ ワークシートをグループ図形にします(var9以降に対応)}
{ by 与太郎 2004/04/03〜2004/04/03 }
{ 2004/04/12 ワークシート図形を選択しても実行するように修正}
{ 〃 ワークシート図形を選択したときは同位置にグループ図形を作成、ワークシート図形を削除する }
{ 〃 列幅がゼロのときは文字を表示しないように修正 }
{ 〃 グリッドの色をシアンに変更 }
{ 2004/08/26 データベースのサブ行も表示するように修正 }
{ 〃 非表示グリッドのクラスを定義 }

{ 図形化したいワークシートを表示、またはワークシート図形を選択して、実行する }
{ 属性はクラス属性で変更可能 }
{ クラス名、クラス属性、セルの余白は好みで書き換えてください。 }
{$ DEBUG}
const
{ クラス名とクラス属性 }
_ClsWSText = 'WS-Text';
_ClsWSGrid = 'WS-Grid';
_ClsWSGridHd = 'WS-Grid_Hide';{ ----2004/8/26 追加 }
_ClsWSOutLine = 'WS-Outline';
_ClsWSBorder = 'WS-Border';
_OutlineWidth = 21;{ 0.53ミリ }
_OutlineColor = 15;{ 赤色 }
_GridWidth = 1;{ 0.025ミリ }
_GridColor = 2;{ シアン }
_GridHdWidth = 1;{ 0.025ミリ }{ ----2004/8/26 追加 }
_GridHdColor = 5;{ 黄色 }{ ----2004/8/26 追加 }
_LnWidth = 11;{ 0.28ミリ }
_LnColor = 4;{ 青色 }
_txtColor = 15;{ 赤色 }
_
{ セルの余白 }
_LeftMargin = 3;{ 3ポイント=1.06ミリ }
_RightMargin = 3;{ 3ポイント=1.06ミリ }

{ オブジェクト識別番号 }
_ShowGrid = 83;{ WSのグリッド表示 }{ ----2004/8/26 追加 }
_
type
_wsCell = structure
__subAlign, { ----2004/8/26 追加 }
__align_:integer;{ 0=標準/1=左よせ/2=センタ/3=右よせ }
__txt_:string;{ セルの内容 }
__fontID_:integer;
__size_:integer;
__Style_:integer;{Plain:0/Bold:1/Italic:2/Underline:4/Outline:8/Shadow:16}
_end;{structure}
_
var
_k_:real;_{ 描画倍率 }
_hWS_:handle;_{ WSのハンドル }
_hTbl_:handle;_{ WS図形のハンドル }
_maxRow, maxClm_:integer;_{ WSの行数,列数 }
_maxRowDB_:integer;_{ サブ行を含んだ行数 }{ ----2004/8/24 追加 }
_indexRDB_:dynArray[] of integer;_{ 行番号→サブ行を含んだ行番号 }{ ----2004/8/24 追加 }
_wd_:dynArray[] of integer;_{ セル幅 }
_ht_:dynArray[] of integer;_{ セル高さ }
_subRows_:dynArray[] of integer;_{ サブ行の数 }{ ----2004/8/24 追加 }
_x_:dynArray[] of real;_{ セル境界のX座標 }
_y_:dynArray[] of real;_{ セル境界のY座標 }
_hLine_:dynArray[,] of boolean;_{ 横罫線の有無 }
_vLine_:dynArray[,] of boolean;_{ 縦罫線の有無 }

procedure Set_k;{ 描画倍率を計算します。 }
var
_scale_:real;
_upi_:real;
_fraction, display_:longint;
_format_:integer;
_name, squareName_:string;
begin
_scale:= GetLScale(ActLayer);
_GetUnits(fraction, display, format, upi, name, squareName);
_k:= upi * scale / 25.4 / 72 * 25.4;
end;{Set_k}

procedure GetWSHandle(var hWS, hTbl:handle);
{ ワークシートとワークシート図形のハンドルを返します。 }
begin
_hWS:= ActSSheet;
_if hWS = nil then begin
__hTbl:= FSActLayer;
__if (hTbl <> nil) & (GetType(hTbl) = 56) then begin
___hWS:= GetWSFromImage(hTbl);
__end;{if}
_end;{if}
end;{GetWSHandle}

function Row2RowDB(row, subRow:integer):integer;
begin
_Row2RowDB:= indexRDB[row] + subRow;
end;{Row2RowDB}

procedure Init_Vars;{ 変数を初期化します。 }
var
_row, rowDB, clm_:integer;{ ----2004/8/24 rowDBを追加 }
_top, left, bottom, right_:boolean;
_
_procedure Set_or(var source:boolean; dist:boolean);
_begin
__source:= source or dist;
_end;{Set_or}
_
_begin{Init_Vars}
__{ 配列を確保 }
__GetWSRowColumnCount(hWS, maxRow, maxClm);
__Allocate indexRDB[0..maxRow];{ ----2004/8/24 追加 }
__Allocate subRows[0..maxRow];{ ----2004/8/24 追加 }
__
_{ ↓2004/8/24 追加 }
__for row:= 1 to maxRow do
___subRows[row]:= 0;
__indexRDB[0]:= 0;
__subRows[0]:= 0;
__for row:= 1 to maxRow do begin
___if IsWSDatabaseRow(hWS, row) then
____GetWSSubrowCount(hWS, row, subRows[row]);
___indexRDB[row]:= indexRDB[row-1] + subRows[row-1] + 1;
__end;{for}
__maxRowDB:= indexRDB[maxRow] + subRows[maxRow];
_{ ↑2004/8/24 追加 }
__
__Allocate ht[1..maxRowDB];
__Allocate wd[1..maxClm];
__Allocate x[0..maxClm];
__Allocate y[0..maxRowDB];
__Allocate hLine[0..maxRowDB, 0..maxClm];
__Allocate vLine[0..maxRowDB, 0..maxClm];
__
__{ セルの寸法を取得 }
__for row:= 1 to maxRow do
___GetWSRowHeight(hWS, row, ht[row]);
__for clm:= 1 to maxClm do
___GetWSColumnWidth(hWS, clm, wd[clm]);
__
__{ 罫線を取得 }
__for row:= 0 to maxRow do begin
___for clm:= 0 to maxClm do begin
____hLine[row, clm]:= false;
____vLine[row, clm]:= false;
___end;{for}
__end;{for}
__
_{ ↓2004/8/26 修正 }
__for row:= 1 to maxRow do begin
___for rowDB:= indexRDB[row]+0 to indexRDB[row]+SubRows[row] do begin
____for clm:= 1 to maxClm do begin
_____GetWSCellBorder(hWS, row, clm, top, left, bottom, right);
_____Set_or(hLine[rowDB-1, clm], top);
_____Set_or(hLine[rowDB, clm], bottom);
_____Set_or(vLine[rowDB, clm-1], left);
_____Set_or(vLine[rowDB, clm], right);
____end;{for}
___end;{for}
__end;{for}
_{ ↑2004/8/24 修正 }
end;{Init_Vars}

procedure Set_XY;{ XY座標を計算します。 }
var
_row, rowDB, clm_:integer;{ ----2004/8/24 rowDBを追加 }
begin
_for clm:= 1 to maxClm do
_x[clm]:= x[clm-1] + k * wd[clm];

{ ↓2004/8/24 修正 }
_for row:= 1 to maxRow do
__for rowDB:= indexRDB[row]+0 to indexRDB[row]+SubRows[row] do
___y[rowDB]:= y[rowDB-1] - k * ht[row];
{ ↑2004/8/24 修正 }
end;{Set_XY}

function BeClass(cls:string):boolean;
{ クラスの有無を返します。 }
var
_i_:integer;
_be_:boolean;
begin
_i:= 1;
_be:= false;
_while (i <= ClassNum) & (not be) do begin
__if cls = ClassList(i) then
__be:= true;
__i:= i + 1;
_end;{while}
_BeClass:= be;
end;{BeClass}

procedure SetClassAttrs;{ ----2004/8/26 修正 }
{ クラス属性を設定します。クラスがある場合は何もしません。 }
_
_procedure SetClsAttr(cls:string; col, wd:integer);
_begin
__if not BeClass(cls) then begin
___NameClass(cls);
___SetClPenFore(cls, col);
___SetClLW(cls, wd);
__end;{if}
_end;{SetClsAttr}
_
begin{SetClassAttrs}
_SetClsAttr(ClsWSGrid, GridColor, GridWidth);
_SetClsAttr(ClsWSGridHd, GridHdColor, GridHdWidth);
_SetClsAttr(ClsWSOutline, OutlineColor, OutlineWidth);
_SetClsAttr(ClsWSBorder, lnColor, lnWidth);
_SetClsAttr(ClsWSText, txtColor, 14);
end;{SetClassAttrs}

procedure DrawGrid;{ ----2004/8/24 修正 }
{ グリッドを描きます。 }
var
_rowDB, clm_:integer;
begin
_BeginGroup;
__for rowDB:= 1 to maxRowDB-1 do begin
___MoveTo(x[0], y[rowDB]);
___LineTo(x[maxClm], y[rowDB]);
__end;{for}
__
__for clm:= 1 to maxClm-1 do begin
___MoveTo(x[clm], y[0]);
___LineTo(x[clm], y[maxRowDB]);
__end;{for}
_EndGroup;
end;{DrawGrid}

procedure DrawOutline;{ ----2004/8/24 修正 }
{ 外枠を描きます。 }
begin
_Rect(x[0], y[0], x[maxClm], y[maxRowDB]);
end;{DrawOutline}

procedure DrawHBorders;{ ----2004/8/24 修正 }
{ 水平線を書きます。 }
var
_rowDB, c1, c2_:integer;
_
_function StartClm(c:integer):integer;
_begin
__repeat
___c:= c + 1;
__until (maxClm <= c) | (hLine[rowDB, c]);
__if (c <= maxClm) & (hLine[rowDB, c]) then
___StartClm:= c
__else
___StartClm:= 0;
_end;{StartClm}
_
_function EndClm(c:integer):integer;
_begin
__while (c < maxClm) & hLine[rowDB, c+1] do
___c:= c + 1;
__EndClm:= c;
_end;{EndClm}
_
begin{DrawHBorders}
_for rowDB:= 0 to maxRowDB do begin
__c1:= StartClm(0);
__while (c1 <> 0) do begin
___c2:= EndClm(c1);
___MoveTo(x[c1-1], y[rowDB]);
___LineTo(x[c2], y[rowDB]);
___c1:= StartClm(c2);
__end{while}
_end;{for}
end;{DrawHBorders}

procedure DrawVBorders;{ ----2004/8/24 修正 }
{ 垂直線を描きます。 }
var
_clm, r1, r2_:integer;
_
_function StartRow(r:integer):integer;
_begin
__repeat
___r:= r + 1;
__until (maxRowDB <= r) | (vLine[r, clm]);
__if (r <= maxRowDB) & (vLine[r, clm]) then
___StartRow:= r
__else
___StartRow:= 0;
_end;{StartRow}
_
_function EndRow(r:integer):integer;
_begin
__while (r < maxRowDB) & vLine[r+1, clm] do
___r:= r + 1;
__EndRow:= r;
_end;{EndRow}

begin{DrawVBorders}
_for clm:= 0 to maxClm do begin
__r1:= StartRow(0);
__while (r1 <> 0) do begin
___MoveTo(x[clm], y[r1-1]);
___LineTo(x[clm], y[r2]);
___r2:= EndRow(r1);
___r1:= StartRow(r2);
__end{while}
_end;{for}
end;{DrawVBorders}

function CellAlign(h:handle; row, clm, subRow:integer):integer;{ ----2004/8/26 追加 }
{ セルの文字揃えを返します。 }
var
_result_:integer;
begin
_GetWSCellAlignment(h, row, clm, result);
_if result = 0 then begin
__if subRow = 0 then begin
___if CellHasNum(h, row, clm) then
____result:= 3
___else
____result:= 1;
__end{if}
__else begin
___if IsWSSubrowCellNumber(h, row, clm, subRow) then
____result:= 3
___else
____result:= 1;
__end;{else}
_end;{if}
_CellAlign:= result;
end;{CellAlign}

procedure DrawTexts;{ ----2004/8/26 修正 }
{ セルの文字を描きます。 }
var
_row, rowDB, subRow, clm_:integer;
_cell_:wsCell;
_xT, yT_:real;
begin
_TextVerticalAlign(5);{ 下揃え }
_for row:= 1 to maxRow do begin
__for clm:= 1 to maxClm do begin
___if (0 < wd[clm]) then begin
____for subRow:= 0 to subRows[row] do begin
_____if subRow = 0 then
______GetWSCellString(hWS, row, clm, cell.txt)
_____else
______GetWSSubrowCellString(hWS, row, clm, subRow, cell.txt);
_____if (cell.txt <> '') then begin
______GetWSCellTextFormat(hWS, row, clm, cell.fontID, cell.size, cell.style);
______cell.align:= CellAlign(hWS, row, clm, subRow);
______case cell.align of
_______0, 1: xT:= x[clm-1] + k * LeftMargin;
_______2: xT:= (x[clm-1] + x[clm]) / 2;
_______3: xT:= x[clm] - k * RightMargin;
______end;{case}
______rowDB:= row2rowDB(row, subRow);
______yT:= y[rowDB];
______TextJust(cell.align);
______TextFont(cell.fontID);
______TextSize(cell.size);
______TextOrigin(xT, yT);
______CreateText(cell.txt);
______SetTextStyle(LNewObj, 0, GetTextLength(LNewObj), cell.style);
_____end;{if}
____end;{for}
___end;{if}
__end;{for}
_end{for}
end;{DrawTexts}

begin{main}
_GetWSHandle(hWS, hTbl);
_if hWS = nil then begin
__AlrtDialog('ワークシートを開くか、選択してください。');
_end{if}
_else begin{ グループ図形を描く }
__PushAttrs;
__DSelectAll;
__Set_k;
__Init_Vars;
__if hTbl = nil then begin
___Message('図形を描く位置(左上)をクリックしてください。');
___GetPt(x[0], y[0]);
__end{if}
__else begin
___GetBBox(hTbl, x[0], y[0], x[maxClm], y[maxRow]);
__end;{else}
__Set_XY;
__SetClassAttrs;
__BeginGroup;
___FillPat(0);
___LSByClass;
___LWByClass;
___PenColorByClass;
___NameClass(ClsWSText);
___DrawTexts;
___if GetObjectVariableBoolean(hWS, ShowGrid) then{ ----2004/8/26 追加 }
____NameClass(ClsWSGrid)
___else
____NameClass(ClsWSGridHd);
___DrawGrid;
___NameClass(ClsWSBorder);
___BeginGroup;
____DrawHBorders;
____DrawVBorders;
___EndGroup;
___NameClass(ClsWSOutline);
___DrawOutline;
__EndGroup;
__if hTbl <> nil then
___DelObject(hTbl)
__else
___ClrMessage;
__PopAttrs;
__ReDrawAll;
_end;{else}
end;{main}
Run(WS_to_GroupObj);


以前、提供してくれた...   石男
email:  Mon Sep 6 13:18:01 2004

以前、与太郎さんが提供してくれたWSをグループ図形に変換するおまじないについて
質問なのですが、サブルーチンのDrawGridとDrawHBorders、DrawVBordersは何か
違いがあるのですか?


クリックした文字を一つにまとめるスクリプト   与太郎
email:  Mon Sep 6 10:46:18 2004

他のCADのデータを取り込んで、テキストが分解されていた時などに使えます。
文字のフォント、サイズ、スタイルは元の属性を再現できましたが、色は再現できませんでした。
(GetTextColor、SetTextColorに相当するサブルーチンがないため)

procedure JoinText;
{ クリックした文字を一つにまとめます。 }
{ Option(Alt)キーを押しながらクリックすると、間にスペースを挿入します。 }
{ 文字以外をクリックすると終了します。 }
{$ DEBUG}
const
TextObj = 10;
var
_x, y_:real;
_h0, h_:handle;
_str, str0_:string;
_lg0, lg_:integer;
_fID, fSize, fStyle_:integer;
_i, j_:integer;
begin
_Message('最初の文字をクリックしてください。');
_DSelectAll;
_GetPt(x, y);
_h0:= PickObject(x, y);
_if h0 <> nil then begin
__if GetType(h0) = TextObj then begin
___SetSelect(h0);
___ReDraw;
___str0:= GetText(h0);
___lg0:= Len(str0);
___Message('次の文字をクリックしてください。');
___GetPt(x, y);
___h:= PickObject(x, y);
___while h <> nil do begin
____if GetType(h) = TextObj then begin
_____if Option then begin
______str0:= Concat(str0, ' ');
______lg0:= lg0 + 1;
_____end;{if}
_____str:= GetText(h);
_____lg:= Len(str);
_____if (lg0+lg) > 255 then begin
______AlrtDialog('255文字を超えてしまいました。');
_____end{if}
_____else begin
______str0:= Concat(str0, str);
______SetText(h0, str0);
______for i:= 0 to lg-1 do begin
_______fID:= GetTextFont(h, i);
_______fSize:= GetTextSize(h, i);
_______fStyle:= GetTextStyle(h, i);
_______SetTextFont(h0, lg0+i, 1, fID);
_______SetTextSize(h0, lg0+i, 1, fSize);
_______SetTextStyle(h0, lg0+i, 1, fStyle);
______end;{for}
______lg0:= lg0 + lg;
______DelObject(h);
______ReDraw;
_____end;{else}
____end{if}
____else begin
_____AlrtDialog('文字図形をクリックしてください。');
____end;{else}
____GetPt(x, y);
____h:= PickObject(x, y);
___end;{while}
__end{if}
__else begin
___AlrtDialog('文字図形をクリックしてください。');
__end;{else}
_end;{if}
_ReDrawAll;
_ClrMessage;
end;
Run(JoinText);


文字図形にテーパーを付けるスクリプト(2)   与太郎
email:  Fri Sep 3 21:02:25 2004

2バイト文字対応版です。
2バイト文字の上位バイトは129〜159と224〜252の範囲です。
(下位バイトの範囲は64〜126と128〜252ですが、今回は必要ありません。)

procedure TaperText;{ 文字図形にテーパーを付けます }
{$ DEBUG}
const
K = -1.5;
Kt = 1/4;{ テーパー比 = 1/4 }
var
h:handle;
sz1, sz2:integer;
i, lg:integer;
k1, k2:real;
s:string;
c:char;
bt:integer;
begin
h:= FSActLayer;
if (h <> nil) & (GetType(h) = 10) then begin
s:= GetText(h);
lg:= GetTextLength(h);
sz1:= GetTextSize(h, 0);
sz2:= sz1 * Kt;
k1:= sz1 * (k);
k2:= (sz2-sz1-k1);
i:= 0;
while (i <= lg-1) do begin
c:= copy(s, i+1, 1);
case Ord(c) of
129..159, 224..252: bt:= 2;
otherwise bt:= 1;
end;{case}
SetTextSize(h, i, bt, sz1 + k2*(i/(lg-1))^2 + K1*(i/(lg-1)));
i:= i + bt;
end;{while}
ReDrawAll;
end;{if}
end;
Run(TaperText);

当然ながら、サイズがゼロより小さくなる設定にすると、表示がおかしくなります。


文字図形にテーパーを付けるスクリプト   与太郎
email:  Thu Sep 2 17:54:39 2004

アクティブレイヤで一番上の選択文字図形にテーパーを付けます。

procedure TaperText;{ 文字図形にテーパーを付けます }
{$ DEBUG}
const
K = -1.5;
Kt = 1/4;{ テーパー比 = 1/4 }
var
h:handle;
sz1, sz2:integer;
i, lg:integer;
k1, k2:real;
begin
h:= FSActLayer;
if (h <> nil) & (GetType(h) = 10) then begin
lg:= GetTextLength(h);
sz1:= GetTextSize(h, 0);
sz2:= sz1 * Kt;
k1:= sz1 * (k);
k2:= (sz2-sz1-k1);
for i:= 1 to lg-1 do begin
SetTextSize(h, i, 1, sz1 + k2*(i/lg)^2 + K1*(i/lg));
end;{for}
ReDrawAll;
end;{if}
end;
Run(TaperText);

k を変えるとテーパー形状が変わります。大きくすると膨らみます。
残念ながら、2バイト文字には対応しておりません。実行すると変になります。
対応させるには、1バイト文字か2バイト文字かを調べないといけません。


Re:タブ区切り   与太郎
email:  Wed Sep 1 11:49:28 2004

おかしいですね。
古いバージョンだと、Write()の引数に関数を使えなかったりしたので、
const Tab1 = Char(9);
 ・
 ・
 ・
Write( s , Tab1 , s2 , Tab1...);
としてみたらどうでしょうか。

もしだめでも、
Write(s); Tab(1);
Write(s2); Tab(1);
 ・
 ・
 ・
とすれば大丈夫だと思います。

表計算ソフトにコピペ出来たり、データの内容を問わない等の理由から、タブ区切り
テキストは最強のデータフォーマットです。是非あきらめずにやってみてください。

一行タブ区切り読み込みはお役に立ちましたか。標準のReed()がブラックボックスで、
いろいろ試してみるのも面倒なので、自前の関数を書きました。


タブ区切り   石男
email:  Wed Sep 1 10:05:58 2004

テキスト吐き出しで、Write( s , Chr(9) , s2 , Chr(9)...));と言ったように
タブ区切りを行うと、うまくタブが書き込まれないようですがバグですかね?
仕方がないのでカンマ区切りで逃げましたが、その際に与太郎さんの一行タブ区切り
読み込みを使わせていただきました...(礼)

VW10.5 MacOS 10.3.2


Excelで数式を計算する(2)   与太郎
email:  Tue Aug 31 12:58:15 2004

数式を計算する関数がない問題は、ExcelにTextCalcを組み込むことで解決できました。この関数マクロは
VBAで書かれています。どうやら数式を括弧、数字、演算子の要素に切り分けて、自前のルーチンで計算し
ているようです。VBAだとこうするしかなかったのでしょうか?
与太郎のCalcStr()は、VBA対応以前だったので、Excel4.0マクロという形式で作りました。EVALUTE()
という、数式文字列を計算するマクロ関数を使ったので、計算ルーチンは書いていません。Excel4.0マクロ
で自前の計算ルーチンを書くのは、困難だったろうと思います(特にデバッグが)。

Excel4.0マクロは、マクロシートに作成します。ところが、MicroSoftはExcel4.0マクロを使わせたくな
いようで、以前は「挿入」メニューに「マクロシート」という項目があったのが、現在ではなくなっていま
す。マクロシートを作るには、ワークシートのタブを右クリックして、コンテキストメニューの「挿入...」
で 「Excel4.0マクロ」を選択します。マクロシートの見かけはワークシートと変わりません。ワークシー
トでは使えないマクロ関数が使えるのが違いです。マクロを入力するときは、値より数式を表示したほうが
見やすいので、「オプション...」または「初期設定...」で「数式」をチェックします。

以下が関数マクロ「CalcStr」です。上から順番に実行する単純なマクロで、ループも分枝もありません。
マクロはB1〜B38セルに入力します。テキストエディタで_をタブに変換すれば、マクロシートにコピペ出
来ます。

B1: _CalcStr_数式文字列を計算する
B2: _=RESULT(1)_関数の返り値(1は実数型)
B3: _=ARGUMENT("STR", 2)_関数の引数を変数STRに代入(2は文字列型)
B4: _=STR_デバッグ用にSTRを表示。(以下も同様)
B5: _STR=LOWER(STR)_大文字を小文字に変換
B6: _=STR
B7: _STR=ASC(STR)_全角文字を半角文字に変換
B8: _=STR
B9: _STR=SUBSTITUTE(STR," ","")_空白をヌル文字に置き換える。(他も同様)
B10: _=STR
B11: _STR=SUBSTITUTE(STR,"{","(")
B12: _STR=SUBSTITUTE(STR,"}",")")
B13: _STR=SUBSTITUTE(STR,"[","(")
B14: _STR=SUBSTITUTE(STR,"]",")")
B15: _=STR
B16: _STR=SUBSTITUTE(STR,"x","*")
B17: _STR=SUBSTITUTE(STR,"×","*")
B18: _STR=SUBSTITUTE(STR,"÷","/")
B19: _STR=SUBSTITUTE(STR,"+","+")
B20: _STR=SUBSTITUTE(STR,"−","-")
B21: _STR=SUBSTITUTE(STR,"・","*")
B22: _=STR
B23: _STR=SUBSTITUTE(STR,"√","SQRT")
B24: _=STR
B25: _STR=SUBSTITUTE(STR,"π","PI()")
B26: _=STR
B27: _STR=SUBSTITUTE(STR,"°","°")_半角カナの"°"を(度)に置き換えてますが、掲示板なので自粛。
B28: _STR=SUBSTITUTE(STR,"°","*pi()/180")
B29: _=STR
B30: _STR=SUBSTITUTE(STR,"tan-1","arctan")
B31: _STR=SUBSTITUTE(STR,"sin-1","arcsin")
B32: _STR=SUBSTITUTE(STR,"cos-1","arccos")
B33: _=STR
B34: _STR=SUBSTITUTE(STR,"/arc","/180*pi()/a")_角度を度で返すための置き換え(下の行も)
B35: _STR=SUBSTITUTE(STR,"arc","180/pi()*a")
B36: _=STR
B37: _=EVALUATE("="&STR)_数式を計算。文字列の形式はセルに入れる式と同じで、先頭に=が必要。
B38: _=RETURN(B37)_B37セルの値を返して終了。

マクロ関数の定義は、B1〜B38セルを選択して、「挿入」−「名前」−「定義...」で行います。そのとき、
「マクロの実行」グループ内の「関数」をチェックします。終わったら保存します。

最初に実行する前に、マクロシートを値表示に戻しておきます。
A1セルに数式を入れ、B1セルに「=CalcStr(A1)」と入れます。
きちんと計算されてたら(されてなくても)、マクロシートを見てください。文字がどう置き換えられてい
くかを確認出来ます。

マクロ関数をアドインにするには、「ファイル」−「別名で保存...」で、フォーマットを「MicroSoft Excel
アドイン」として、所定のフォルダに保存します(フォルダはExcelのバージョンやOSによって異なります)。
アドインをExcelに登録するには、Excelを再起動して、「ツール」−「アドイン」で「CalcStr」をチェック
します。以後は普通のExcel関数とおなじようにCalcStr()を使えます。

TextCalcと比べて単純なので、トラブルも少ないかもです。


Re2:Excelで数式を計算する   与太郎
email:  Sat Aug 28 18:46:28 2004

ARcoatingさん、「Textcalc」の御紹介ありがとうございました!
似たような関数を誰かが作ってるだろうと思ってましたが、本気で探してなかったということもあっ
て、今まで見つけられませんでした。
アドオンですと、使い勝手がいいですね。
マクロシートだと、関数名の前にマクロファイルの名前を付ける必要があるのでした。
例: =CalcStr() → =MacroFile!CalcStr()
コピペすればいいので,今までそれほど不便と思わずに使っておりましたが、やっぱり不便でした。
今からでも(遅蒔きながら)アドインにしてみるつもりです。


re;Excelで数式を計算する  ARcoating
email:  Sat Aug 28 11:26:31 2004

こんにちは、お久しぶりです!
エクセルの数式について、私も積算時にいつも往生しております、、、。
最近は与太郎さんが言われているCalcStr()の様なもの?を利用しております。
フリーの関数アドインで「Textcalc」というのをエクセル登録して利用させてもらってます。
http://homepage3.nifty.com/peace/
動作が重くなったり、たまに数式エラーがでますがなかなか優秀です。
ご参考までに、、。


Excelで数式を計算する(1)   与太郎
email:  Fri Aug 27 20:04:00 2004

VWと関係ない話ですが...
みなさんは、Excelで数式を書くときはどうされているでしょうか?
たとえば、 12.00 x 4.00 x 2.50 = 120.00(m3) と書く場合、
┌─┬─────┬─┬────┬─┬────┬─┬─────
│ │__A__│B│_C__│D│_E__│F│__G__
├─┼─────┼─┼────┼─┼────┼─┼─────
│1│12.00│x│4.00│x│2.50│=│=A1*C1*E1
└─┴─────┴─┴────┴─┴────┴─┴─────
とするのが一般的だと思います。この方法だと、同じ形式のデータが何行もあるときに、縦方向が揃って
綺麗です。

しかし、三角形や台形の式が混じった場合は面倒なことになります。たとえば、
12.00 x 4.00 x 2.50 = 120.00
10.50 x 6.00 x 3.50 / 2 = 110.25
6.50 x 4.00 x ( 5.50 + 3.00 ) / 2 = 110.50
のような場合(コンクリート体積等の計算式が必要なので、こういうのが結構あります)、
┌─┬─────┬─┬────┬──┬────┬─┬────┬──┬─┬─┬─────────
│ │__A__│B│_C__│D_│_E__│F│_G__│H_│I│J│____K____
├─┼─────┼─┼────┼──┼────┼─┼────┼──┼─┼─┼─────────
│1│12.00│x│4.00│x │2.50│ │____│__│_│=│=A1*C1*E1
├─┼─────┼─┼────┼──┼────┼─┼────┼──┼─┼─┼─────────
│2│10.50│x│6.00│x │3.50│/│2___│__│_│=│=A2*C2*E2/G2
├─┼─────┼─┼────┼──┼────┼─┼────┼──┼─┼─┼─────────
│3│ 6.50│x│4.00│x(│5.50│+│3.00│)/│2│=│=A3*C3*(E3+G3)/I3
└─┴─────┴─┴────┴──┴────┴─┴────┴──┴─┴─┴─────────
という具合になるでしょうか。もちろん、D列やH列を工夫して、"x"と"x("や、"="と")="を自動的に書
き分けたり、条件式を使ってK列を一つの計算式で済ませることは出来ますが、ワークシートはますます
複雑になります。ミスも多くなりそうです。

ワークシートを単純にするには、
┌─┬───────────────────────┬─┬──────
│ │___________A___________│B│__C___
├─┼───────────────────────┼─┼──────
│1│12.00x4.00x2.50________│=│=CalcStr(A1)
├─┼───────────────────────┼─┼──────
│2│10.50x6.00x3.50/2______│=│=CalcStr(A2)
├─┼───────────────────────┼─┼──────
│3│6.50x4.00x(5.50+3.00)/2│=│=CalcStr(A3)
└─┴───────────────────────┴─┴──────
とすることです。この方法だと縦方向は揃いませんが、どんな式が並んでも、ワークシートは単純な構成
になります。式の入力さえ間違えなければ、計算間違いもありません。

問題は、Excelに CalcStr()という関数がないことです。ってそれじゃ意味ないじゃん。

(来週に続く。)


Re5:データベースの構築するのに、   江戸の黒板当番
email:  Fri Aug 27 12:19:10 2004

>今ではHiBaseでこと足りているので、他のアプリは使っていません...。
そう、東京のオフ会のネタはHiBaseで那須の麓でBBQをしながらHiBaseの
使い方のレクチャーということにしません?
羽田氏絶賛の黒磯の温泉まんじゅうと屋外プール顔負けの北温泉それに
帰り道には宇都宮のみんみんの餃子とネタには困らない豪華ツアー付き
紅葉前線の南下の前に(お山での凍死を避けるために)関東の尖り好みの
皆さんいかがでしょう?
サンプルのHiBaseがいまいちピンときていなんですよ。それなもんで
そこからまでとそこからどうなるのがすごく気になるんです。
最低予定人数3名様程度でいかがですか。東京のXOOPがへそを曲げているので
ここのカフェテラスに話題を移したいと思います。


Re4:データベースの構築するのに、   与太郎
email:  Thu Aug 26 17:54:30 2004

>石男さん
VWで作図 → FileMakerで見積り作成ですか。完全自動化なら羨ましい。

こちらは、アプリ間の連携は「コピペ」です。あとはスクリプトでレイヤ毎の断面数量をテキスト
ファイルに書き出すくらいです。それをExcelに貼り付けて、ごちゃごちゃやって、数量計算書に
しています。転記ミスがないだけましというレベルです。
VWの断面図とExcelの計算書を連動させるなんて、夢の夢です。


Re3:データベースの構築するのに、   石男
email:  Thu Aug 26 8:36:58 2004

一時、DBにはまって?いた時は、VSでテキストファイルを取り出しFileMakerに読み込
ませていました。この一連の流れをAppleScriptで制御していました。これはExcelでも
同じように出来す、ただWinですとアプリ間を連携させるScriptがあるかな〜。
VSはVBに対応していないし...。
今ではHiBaseでこと足りているので、他のアプリは使っていません...。


Re2:データベースの構築するのに、   与太郎
email:  Wed Aug 25 22:00:41 2004

>一休さん
ひとくちにデータベースといっても、データベースソフト、表計算ソフト、テキストファイルなど、
いろいろな方法があると思うのですが、一休さんはExcelで作られてるのですか。(こっそりと)詳し
く教えていただけたら、お助けできるかもしれません。
といっても、与太郎は何年も前にFileMakerと4thDimensionを触ったことがあるだけで、実際に使った
こともないので、あまり役に立てない可能性も大です。半分興味本位ですが、お許しを(^_^)。


Re:WS_to_GroupObj を、データベース対応に修正しました。   与太郎
email:  Tue Aug 24 21:35:34 2004

あっ間違えてリターンを押してしまった。

IsWSSubrowCellString() と IsWSSubrowCellNumber() でDB従属行も調査できましたね。
失礼いたしました。


Re: 
email:  Tue Aug 24 21:29:57 2004

IsWSSubrowCellString()


WS_to_GroupObj を、データベースの対応に修正しました。   与太郎
email:  Mon Aug 23 20:00:42 2004

↓やっぱりデータベースって使うんだ(私は使わないんですが)。
というわけで、WS_to_GroupObj を、データベースの従属行も表示出来るように修正しました。

ただし、位置揃えが標準で、従属行が文字データの場合、左揃えで表示しないといけないのですが、
データベースのヘッダ行が数値データのため、右揃えで表示してしまいます。
CellHasNum()、CellHasStr() ではヘッダ行しか調べられないので、仕方ありませんが、もしも解決
法をご存知の方がいらっしゃいましたら、教えていただけたら助かります。

ということで、ソースの書き込みはしばらく待ってみます(ご要望があれば別ですが)。
400行近くなってしまったため、何度も書き込むのも何なので...。


Re.:データベースの構築するのに、   江戸の黒板当番
email:  Sun Aug 22 19:45:26 2004

ODBC経由FileMakerとHiBaseでの図形データベースの道があるのですが
難解でよく解っていません。
ODBC経由FileMakerは
http://www.aecmgr.com/pages/2/index.htm
HiBaseは製品版のVW10から紹介されています。
ホロン社はhttp://www.hln.co.jp/hibase/index.htmlですが
Mac OSX Server版の開発が遅れていることなどで利用体制が
整っていません。ここまでこっそりばらしたんですから一休さんが
この世界の第一人者への道に乗ってしまいましたのでがんばってくださいね。


データベースの構築するのに、   一休
email:  Sun Aug 22 10:46:32 2004

 今までは、ワークシートの数量をタブ区切りにエクスポートしてエクセルでインポートという作業をしていますが、もっと他のソフトとの連携がうまくいく方法ありませんかね?
 ベクターなんだかでエクスポートしたらデータベースの値も変わるという連携は
可能でしょうか? もし可能でしたら、その組み合わせ、エクスポート形式を教えていただけないでしょうか? しかもこっそり笑


出し遅れの証文のような...、アクティブクラスを変更するスクリプト   与太郎
email:  Sun Aug 15 20:52:33 2004

MC7までは問題なかったのですが、VW8以降、クラス名にハイフンを含んでいるとサブメニューに
なってしまい選択しづらいので、こんなスクリプトを作ってみました。PIMにして、ショートカット
キーを割り当てて使います。
VW10からはアクティブクラスをショートカットキーで変更できるようになったので、このスクリプ
トは必要ありません。

クラスの並べ替えにマージソート(みたいなもの)を使っていますが、普通こんなところでは使いま
せん。100個程度のデータのソートなら、どんなソートアルゴリズムでも一瞬で済むので、最も簡単
なアルゴリズムを使うべきでした。あと、文字列の大小を < や > 比較できれなかったので、LargeStr
で比較しています。

一応クラス数は255までとしています。私自身は50個もあれば十分ですが、3Dの建築で建具のテクス
チャー毎にクラスを作ったりすると255個を超えたりするのでしょうか?

じつは、スクリプトの最後の Layer(GetLName(ActLayer)); がないと、スクリプト実行後、マウスを
動かさないとデータバーのクラスの表示が変わりません(VW8.5/Mac)。それで今まで発表を控えて
いました。クラス変更後に図形を描けばクラス表示も更新されるので、図形を描いた後 DelObject
で削除したり、Redraw したり色々試してみましたがダメでした。それでずっとそのまま使っていまし
たが、数日前、アクティブレイヤを変更して、また戻せばクラス表示が更新されるのに気付きました。
結局、Layer(); を実行すれば良いと判ったので、最後に1行を追加しました。

procedure ActiveNextClass;
{ 「次のクラス」コマンド }
const
_MaxClassNum = 255;
var
_act_:string;
_i, n_:integer;
_cls_:array[1..MaxClassNum] of string;
_
_procedure SwapStr(var s1, s2:string);{ 2つの文字列変数の中身を入れ替える。 }
_var
__s_:string;
_begin
__s:= s2;
__s2:= s1;
__s1:= s;
_end;{SwapStr}
_
_function LargeStr(s1, s2:string):boolean;{ s1がs2より大きければTrueを返す。 }
_var
__i_:integer;
__lg_:integer;
__n, n1, n2_:integer;
__c1, c2_:char;
_begin
__n1:= Len(s1);
__n2:= Len(s2);
__if n1 < n2 then
___n:= n1
__else
___n:= n2;
__lg:= 0;
__i:= 1;
__while (lg = 0) & (i <= n) do begin
___c1:= Copy(s1, i, 1);
___c2:= Copy(s2, i, 1);
___if Ord(c1) > Ord(c2) then
____lg:= 1
___else if Ord(c1) < Ord(c2) then
____lg:= -1;
___i:= i + 1;
__end;
__case lg of
___-1:_LargeStr:= false;
___0:_if n1 > n2 then
_____LargeStr:= true
____else
_____LargeStr:= false;
___1:_LargeStr:= true;
__end;
_end;{LargeStr}
_
_procedure MargeCls(st1, ed1, st2, ed2:integer);{ 配列clsのst1からed1の範囲と、st2からed2の範囲を
ソートする。 ただし、st2 = ed1 + 1 }
_var
__i, j, i1, i2:integer;
__s_:array[1..MaxClassNum] of string;
_begin
__i1:= st1;
__i2:= st2;
__i:= st1;
__while (i <= ed2) do begin
___if LargeStr(cls[i1], cls[i2]) then begin
____s[i]:= cls[i2];
____if i2 < ed2 then
_____i2:= i2 + 1
____else
_____cls[i2]:= chr(255);
___end
___else begin
____s[i]:= cls[i1];
____if i1 < ed1 then
_____i1:= i1 + 1
____else
_____cls[i1]:= chr(255);
___end;
___i:= i + 1;
__end;
__for i:= st1 to ed2 do
___cls[i]:= s[i];
_end;{MargeCls}
_
_procedure SortCls(st, ed:integer);{ 配列clsのstからedの範囲をソートする。 }
_var
__st1, ed1, st2, ed2_:integer;
_begin
__if 1 < (ed-st) then begin
___st1:= st;
___ed1:= (ed + st) div 2;
___st2:= ed1 + 1;
___ed2:= ed;
___SortCls(st1, ed1);
___SortCls(st2, ed2);
___MargeCls(st1, ed1, st2, ed2);
__end
__else if 1 = (ed-st) then begin
___if LargeStr(cls[st], cls[ed]) then
____SwapStr(cls[st], cls[ed]);
__end;
_end;{SortCls}
_
begin{main}
_act:= ActiveClass;
_n:= ClassNum;
_for i:= 1 to n do begin
__cls[i]:= ClassList(i);
__if cls[i] = '' then
___cls[i]:= '一般';
_end;
_SortCls(1, n);{ VW9以降ならSortArrayが使える? 使えたらサブルーチンは不要。 }
_i:= 1;
_while (i < n) & (act <> cls[i]) do
__i:= i + 1;
_if act = cls[i] then begin
__if i < n then
___i:= i + 1
__else
___i:= 1;
_end;
_NameClass(cls[i]);
_Layer(GetLName(ActLayer));{ データバーの更新に必要。 }
end;{main}
Run(ActiveNextClass);

けっこう長いスクリプトですが、大半はクラス名をソートするサブルーチンです。


ForEachObject...互換?   与太郎
email:  Tue Aug 10 22:15:50 2004

ForEachObject...を使わずに全図形にアクセスする方法を考えてみました。
動作確認はしていません。それに、たぶんForEachObject...を使ったほうが簡単です。

procedure DelHideClassObj;
{ 表示してないクラス(&グレー)の図形を削除します。 }
{ グループ内の図形も削除しますが、グループ図形自体は削除しません。 }
var
_h_:handle;
_
_procedure DoObject(h:handle);
_{ ForEachObject...でいう、actionFuncです。 }
_{ このスクリプトでは、表示してないクラスの図形を削除します。 }
__
__function IsHideObj(h:handle):boolean;
__var
___result_:boolean;
__begin
___if GetCVis(GetClass(h)) = 0 then
____result:= false
___else
____result:= true;
___IsHideObj:= result;
__end;{IsHideObj}
_
_begin{DoObject}
__if IsHideObj(h) then
___DelObject(h);
_end;{DoObject}
_
_procedure DoRepeat(h:handle);
_var
__hC_:handle;
_begin
__while h <> nil do begin
___case GetType(h) of
____11: begin hC:= FInGroup(h); DoRepeat(hC); h:= NextObj(h); end;{ グループ }
____16: begin hC:= FInSymDef(h); DoRepeat(hC); h:= NextSymDef(h); end;{ シンボル定義 }
____31: begin hC:= FInLayer(h); DoRepeat(hC); h:= NextLayer(h); end;{ レイヤー }
____92: begin hC:= FInFolder(h); DoRepeat(hC); h:= NextSymDef(h); end;{ シンボルフォルダ }
____otherwise begin DoObject(h); h:= NextObj(h); end;{ その他 }
___end;{case}
__end;{while}
_end;{DoRepeat}
_
begin{main}
_h:= FLayer; DoRepeat(h);{ ForEachObjectInLayerと同等。全レイヤの図形を処理する。 }
_h:= FSymDef; DoRepeat(h);{ ForEachObjectInListと同等。全シンボル定義内の図形を処理する。 }
end;{main}
Run(DelHideClassObj);

ところで、(全然別の話ですが、)
h:=GetParent(レイヤーハンドル); で返ってくるハンドルのタイプが32になっていますが、これは書類
(ファイル)のハンドルと考えて良いのでしょうか?
だとしても、データベースを割り当てるくらいしか出来ませんし(出来るかどうかは未確認です)、出
来たとしても、非公開の情報なので、バージョンアップでどう転んでも文句はいえません。

ですが、
layerHandle:=FLayer(documentHandle); などと出来ると、マルチドキュメントなスクリプトが書けるの
ですがね。NextDocment()、ActDocment、FDocment、GetDocName()、NumDocment などの関数があれば、
ファイル間で図形を移動(コピー)したりとか、色々出来そうです。
反面、スクリプトのバグで開いている書類が全滅、という事態もありえますが。


Excelでスクリプトを作る方法(6)   与太郎
email:  Fri Jul 30 17:57:01 2004

メッシュデータから3D基準点を描きます。

1. 元のデータを用意する。
一応10mのメッシュとしておきます。(側点間=10m)
┌─┬────┬─────┬─────┬─────┬
│_│__A_│__B__│__C__│__D__│
├─┼────┼─────┼─────┼─────┼
│1│ Y\X│−10.0│__0.0│+10.0│
├─┼────┼─────┼─────┼─────┼
│2│10.0│__0.0│_−0.5│_−1.1│
├─┼────┼─────┼─────┼─────┼
│3│20.0│_−0.6│_−1.1│_−1.7│
├─┼────┼─────┼─────┼─────┼
│4│30.0│_−1.1│_−1.6│_−2.2│
├─┼────┼─────┼─────┼─────┼

2. B12〜D14セルに式を入れる。
セル:B12 ="Locus3D(" & B$1 & ", " & $A3 & ", " & B2 & ");"
残りのセルはB12セルをコピペします。

結果は下のようになります。
セル:B12〜D12 Locus3D(-10, 10, 0); Locus3D(0, 10, -0.5); Locus3D(10, 10, -1.1);
セル:B13〜D13 Locus3D(-10, 20, -0.6); Locus3D(0, 20, -1.1); Locus3D(10, 20, -1.7);
セル:B14〜D14 Locus3D(-10, 30, -1.1); Locus3D(0, 30, -1.6); Locus3D(10, 30, -2.2);

以下省略。


Excelでスクリプトを作る方法(5)   与太郎
email:  Wed Jul 28 21:40:52 2004

メッシュデータから複数の断面の地盤線を描きます。
レイヤ名=断面の名前=測点番号とします。

1. 元のデータを用意する。
一応10mのメッシュとしておきます。(側点間=10m)
┌─┬────┬─────┬─────┬─────┬
│_│__A_│__B__│__C__│__D__│
├─┼────┼─────┼─────┼─────┼
│1│____│−10.0│__0.0│+10.0│
├─┼────┼─────┼─────┼─────┼
│2│測点番号│_____│_____│_____│
├─┼────┼─────┼─────┼─────┼
│3│No.1│__0.0│_−0.5│_−1.1│
├─┼────┼─────┼─────┼─────┼
│4│No.2│_−0.6│_−1.1│_−1.7│
├─┼────┼─────┼─────┼─────┼
│5│No.3│_−1.1│_−1.6│_−2.2│
├─┼────┼─────┼─────┼─────┼

2. E3〜F5セルに式を入れる。
セル:E3 ="Layer('" & A3 & "');"
セル:E4 ="Layer('" & A4 & "');"
セル:E5 ="Layer('" & A5 & "');"
セル:F3 ="Poly(" & B$1 & ", " & B3 & ", " & C$1 & ", " & C3 & ", " & D$1 & ", " & D3 & ");"
セル:F4 ="Poly(" & B$1 & ", " & B4 & ", " & C$1 & ", " & C4 & ", " & D$1 & ", " & D4 & ");"
セル:F5 ="Poly(" & B$1 & ", " & B5 & ", " & C$1 & ", " & C5 & ", " & D$1 & ", " & D5 & ");"
4行目以降は3行目をコピペすればOKです。

B1とかC1でなく、B$1やC$1と書く理由は、3行目をタイプして4行目以下にコピぺしたときに、B2と
かC2に変わらないようにするためです。B3やC3はコピぺしたときにB4やC4に変わってほしいので、$
は入れません。

結果は下のようになります。
Layer('No.1'); Poly(-10 , 0, 0, -0.5, 10, -1.1);
Layer('No.2'); Poly(-10, -0.6, 0, -1.1, 10, -1.7);
Layer('No.3'); Poly(-10, -1.1, 0, -1.6, 10, -2.2);
スクリプトの先頭には、OpenPoly; と書いておきます。
実行すると、指定したレイヤに地盤線を描いてくれます。レイヤがなければ新しく作ってくれます。
ただし新しいレイヤは一番上に作られるので、レイヤの順番を確認する必要はあります。


ところで上の方法だと,横方向のデータが増えたとき、式が長くてたいへんです。次のようにすると、
セルは増えますが式は簡単になります。また、ワークシートが横に広がりすぎるので、縦方向を合わ
せて、データと式を同じ列にします。ここでは式の行はデータの10行下にしておきます。
セル:A13 ="Layer('" & A3 & "'); "
セル:B13 =A13 & "Poly(" & B$1 & ", " & B3
セル:C13 =B13 & ", " & C$1 & ", " & C3
セル:D13 =C13 & ", " & D$1 & ", " & D3
セル:E13 =D13 & ");"
セル幅がせまくてA列〜D列の結果が表示できませんが、途中結果なので構いません。E列が最終結
果です。

結果は、
セル:A13 Layer('No.1'); Poly(
セル:B13 Layer('No.1'); Poly(-10 , 0
セル:C13 Layer('No.1'); Poly(-10 , 0, 0, -0.5
セル:D13 Layer('No.1'); Poly(-10 , 0, 0, -0.5, 10, -1.1
セル:E13 Layer('No.1'); Poly(-10 , 0, 0, -0.5, 10, -1.1);
となります。
テキストエディタにはE列だけコピペします。

頂点データを増やすときは、最初にE列をデータの右隣にコピペ(移動ではない)しておき、C列か
D列を残りの列にコピペします。

全部を一つのレイヤに描かせて多段柱状体にすれば、3Dの地盤を作ることも出来ます。


Excelでスクリプトを作る方法(4)   与太郎
email:  Tue Jul 27 9:31:51 2004

多角形の頂点にシンボルを描きます。(多角形は描きません)
シンボルはスクリプトを実行する前に作っておきます。シンボル名は「頂点シンボル」と
しておきます。ついでに名前(ps1、ps2、ps3)も付けます。

1. 元のデータを用意する。
┌─┬────┬──────┬─────┬─────┬─────┬
│_│__A_│__B___│__C__│__D__│__E__│
├─┼────┼──────┼─────┼─────┼─────┼
│1│頂点番号│__B___│_X座標_│_Y座標_│_回転角_│
├─┼────┼──────┼─────┼─────┼─────┼
│2│_ps1│頂点シンボル│____0│____0│____0│
├─┼────┼──────┼─────┼─────┼─────┼
│3│_ps2│頂点シンボル│__1.2│_1.44│____0│
├─┼────┼──────┼─────┼─────┼─────┼
│4│_ps3│頂点シンボル│__2.4│_5.76│____0│
├─┼────┼──────┼─────┼─────┼─────┼
※回転角は、シンボルの回転角です。

2. F2〜G4セルに式を入れる。
セル:F2 ="NameObject('" & A2 & "');"
セル:F3 ="NameObject('" & A3 & "');"
セル:F4 ="NameObject('" & A4 & "');"
セル:G2 ="Symbol('" & B2 & "', " & C2 & ", " & D2 & ", "& E2 &");"
セル:G3 ="Symbol('" & B3 & "', " & C3 & ", " & D3 & ", "& E3 &");"
セル:G4 ="Symbol('" & B4 & "', " & C4 & ", " & D4 & ", "& E4 &");"

結果は下のようになります。
NameObject('ps1'); Symbol('頂点シンボル', 0, 0, 0);
NameObject('ps2'); Symbol('頂点シンボル', 1.2, 1.44, 0);
NameObject('ps3'); Symbol('頂点シンボル', 2.4, 5.76, 0);

以下省略。


Excelでスクリプトを作る方法(3)   与太郎
email:  Tue Jul 27 9:29:32 2004

多角形の頂点に基準点を描きます。(多角形は描きません)
ついでに基準点に名前も付けてみます。名前は「p1」、「p2」、「p3」とします。

1. 元のデータを用意する。
┌─┬────┬─────┬─────┬
│_│__A_│__B__│__C__│
├─┼────┼─────┼─────┼
│1│頂点番号│_X座標_│_Y座標_│
├─┼────┼─────┼─────┼
│2│__p1│____0│____0│
├─┼────┼─────┼─────┼
│3│__p2│__1.2│_1.44│
├─┼────┼─────┼─────┼
│4│__p3│__2.4│_5.76│
├─┼────┼─────┼─────┼

2. D2〜E4セルに式を入れる。
セル:D2 ="NameObject('" & A2 & "');" セル:E2 ="LoCus(" & B2 & ", " & C2 & ");"
セル:D3 ="NameObject('" & A3 & "');" セル:E3 ="LoCus(" & B3 & ", " & C3 & ");"
セル:D4 ="NameObject('" & A4 & "');" セル:E4 ="LoCus(" & B4 & ", " & C4 & ");"

'と"が紛らわしいので気を付けてください。(私もまちがえました)
VWでは文字列を'と'で囲み、Excelでは"と"で囲みます。
2行目をタイプしたら、3行目と4行目は2行目をコピペすればOKです。
D2〜E4の結果は下のようになります。
NameObj('p1'); Locus(0 , 0);
NameObj('p2'); Locus(1.2 , 1.44);
NameObj('p3'); Locus(2.4 , 5.76);

以下省略。


Excelでスクリプトを作る方法(2)訂正   与太郎
email:  Mon Jul 26 10:22:30 2004

もうすこし使いまわしが利く方法を紹介します。VWのワークシートでは出来ない方法です。
今回は多角形を書くのに別の書式を使います。(以下)
BeginPoly;
AddPoly(X座標1, Y座標1);
AddPoly(X座標2, Y座標2);
.
.
.
AddPoly(X座標n, Y座標n);
EndPoly;

1. 元データを用意する。
┌─┬─────┬─────┬
│_│__A__│__B__│
├─┼─────┼─────┼
│1│_____│_____│
├─┼─────┼─────┼
│2│_X座標_│_Y座標_│
├─┼─────┼─────┼
│3│____0│____0│
├─┼─────┼─────┼
│4│__1.2│_1.44│
├─┼─────┼─────┼
│5│__2.4│_5.76│
├─┼─────┼─────┼

2. C列に式を打ち込む。
┌─┬─────┬─────┬───────────────────
│_│__A__│__B__│__C________________
├─┼─────┼─────┼───────────────────
│1│_____│_____│ClosePoly;
├─┼─────┼─────┼───────────────────
│2│_X座標_│_Y座標_│BeginPoly;
├─┼─────┼─────┼───────────────────
│3│____0│____0│="AddPoly(" & A3 & ", " & B3 & ");"
├─┼─────┼─────┼───────────────────
│4│__1.2│_1.44│="AddPoly(" & A4 & ", " & B4 & ");"
├─┼─────┼─────┼───────────────────
│5│__2.4│_5.76│="AddPoly(" & A4 & ", " & B4 & ");"
├─┼─────┼─────┼───────────────────
│6│_____│_____│EndPoly;
├─┼─────┼─────┼───────────────────

C列の表示は下のようになります。
ClosePoly;
BeginPoly;
AddPoly(0, 0);
AddPoly(1.2, 1.44);
AddPoly(2.4, 5.76);
EndPoly;


3. C1〜C6の範囲をテキストエディタにコピペして、テキストファイルとして保存する。
4. (VWの)「ファイル」−「取り込む」−「VectorScript...」で読み込む。(終わり)

AddPolyの行を変更(追加,削除)することで、別の多角形も簡単に作れます。


削除依頼   与太郎
email:  Mon Jul 26 10:16:12 2004

毎度まいどの削除依頼で申し訳ありませが、
「Excelでスクリプトを作る方法(2)」の削除をお願いします。
”と’を間違えてしまいました^^;)。


Excelでスクリプトを作る方法   与太郎
email:  Fri Jul 23 20:47:58 2004

座標リストから多角形を作図するとき、数字をダイアログで打ち込むのは面倒ですが、
簡単なスクリプトで多角形を描かすことができます。
多角形を描くスクリプトは、
ClosePoly;
Poly(X座標1, Y座標1, X座標2, Y座標2...X座標n, Y座標n);
の2行です。
1行目のClosePoly; は、これ以降の多角形を閉じるというコマンドです。OpenPoly;
なら閉じません。
2行目が多角形生成コマンドです。
やっぱり数字を打ち込むのかとか、一行に収まらないくらい長かったらどうするんだと
お思いでしょうが、VectorScriptはカンマやカッコの前後で改行できるので、
ClosePoly;
Poly(
X座標1, Y座標1,
X座標2, Y座標2,
.
.
.
X座標n, Y座標n
);
のように書くことが出来ます。そして、この形式だとテキストエディタよりExcelを使っ
たほうがメリットがあります。(VWのワークシートでも可能ですが、Excelで作ったほう
が簡単です。)

例として、
1. はじめに、Excelに頂点の座標を打ち込みます。ダイアログやテキストエディタに打
ち込むより楽だと思います。データがあるならコピペで済みます。
┌─┬─────┬─────┬
│_│__A__│__B__│
├─┼─────┼─────┼
│1│_X座標_│_Y座標_│
├─┼─────┼─────┼
│2│____0│____0│
├─┼─────┼─────┼
│3│__1.2│_1.44│
├─┼─────┼─────┼
│4│__2.4│_5.76│
├─┼─────┼─────┼
(※レイアウトの都合で全角文字にしていますが、実際は半角文字です。_は無視して
ください)

2. コマンドやカンマを入れる為に、行と列を挿入して、下のように仕上げる。
┌─┬─────┬─┬────┬──┬
│_│__A__│B│_C__│D_│
├─┼─────┼─┼────┼──┼
│1│ClosePoly;__│__│
├─┼─────┼─┼────┼──┼
│2│Poly(│_│____│__│
├─┼─────┼─┼────┼──┼
│3│____0│,│___0│,_│
├─┼─────┼─┼────┼──┼
│4│__1.2│,│1.44│,_│
├─┼─────┼─┼────┼──┼
│5│__2.4│,│5.76│__│
├─┼─────┼─┼────┼──┼
│6│);___│_│____│__│
├─┼─────┼─┼────┼──┼

3. A1〜D6の範囲をコピーして、テキストエディタにペーストし、
4. テキストファイルとして保存する。
テキストファイルの内容は、下のようになっています。
ClosePoly;
Poly(
0 , 0,
1.2 , 1.44,
2.4 , 5.76
);

5. (VWの)「ファイル」−「取り込む」−「VectorScript...」で読み込む。
これで多角形が出来ているはずです。

面倒だと感じるかも知れませんが、頂点が多い場合はこちらのほうが楽だと思います。テ
キストファイルが残る点や、座標のチェックが容易なのも利点です。

もちろん、テキストファイルに保存したり、VWのワークシートに入力(またはコピペ)し
た座標データから多角形を生成するスクリプトを書く事もできます(私も含めて多くの人
が実際に作って使ってるいます)が、それなりの約束事があり、それがスクリプトを書く
上での最初のハードルになっています。
しかしこのような座標入力のついでに作ってしまえるスクリプトなら、ハードルもずいぶ
ん低くなる思いますが、どうでしょうか。


登録画面でスクリプトを実行する。(2)   与太郎
email:  Tue Jul 20 18:46:50 2004

VW9からは「マクロ編集...」ボタンが「スクリプト編集...」ボタンに変わってますね。


登録画面でスクリプトを実行する。   与太郎
email:  Tue Jul 20 8:50:18 2004

登録画面で画面表示を切り替えると同時に、スクリプトを実行することが可能です。
たとえば、画面切り替えと同時に、座標原点やグリッドを変更したり、カラー表示/白黒
表示を切り替えたりできます。
登録画面で実行するスクリプトを作成するには、登録画面の編集ダイアログの「キャンセ
ル」ボタンの上の「マクロ編集...」ボタンをクリックします。
「マクロ編集...」ボタンは、登録画面作成時には現れません。一旦登録画面を作ってから、
リソースパレットかコマンドパレットから編集ダイアログを開くと、「マクロ編集...」ボ
タンが現れます。
注意する点は、使う側からはスクリプトの有無が判らないことです。(知らない人が使う
と、勝手に設定が変わるので、VWのバグだと思われかねないので、説明が必要です)


業務連絡   管理人
email:
manager@vwch.infonav.net  Mon Jul 19 12:09:43 2004

書き込みをバックナンバーに送りました。
よろしくお願いいたします。