2008年3月29日土曜日

第87回目 図形作成システムの全体像

○第87回目 図形作成システムの全体像

 これまでに作られた、図形作成システムの全体像を見てみます。
 当初考えていたものから、もっともっととなって、2倍から3倍近く膨らんでしまいました。やはり実際に使ってみて資料を作ってみると、もっと機能がほしいということになってしまいました。
 共通マクロを除くと、31個の機能となっています。機能的にはだぶっているのもあります。例えば、"その他の属性情報により図形を修正"は、【図形の属性の修正】とほとんどダブっているといえます。図形作成管理表に書き込むことにより、個別に操作しなくても図形を修正することができます。ケースバイケースで使用してください。個人的には、図形を見ながら個別の属性を修正するというのが、性にあっているようです。

 これで、図形作成にかかるマクロに関する説明は終了することにします。

【図形を作成・削除】
 図形の複数一括作成
 図形をコネクタで結ぶ(コネクタの作成)
 図形_画像の埋込み
 図形の削除
 コネクタの削除

【図形の位置の調整】
 図形の移動_場所を指定する
 図形の整列(複数の図形をある基準で整列させる)
 一つの図形の移動
 図形の移動_整列もどき(規則性を持たせて並べる)

【図形の属性の修正】
 図形の種類の変更
 図形のテキストの修正
 文字の変更
 文字の配置
 図形サイズの変更
 図形_色の選択
 図形の外枠の設定_消去
 図形の回転
 図形ライン_コネクタの修飾
  ラインの太さ
  矢印の向き
  点線化

【図形の属性の高度な修正】
 図形のサイズ等を合わせる
 その他の属性情報により図形を修正

【図形情報の取得】
 図形のテキストの取得_書き込み
 図形の位置情報の取得
 コネクタの場所の取得
 図形のその他の属性の取得
 図形情報の一括取得

【その他】
 図形のテキストに図形の番号を追加_削除
 図形のグループ化及び解除
 図形の順序
 図形番号の並べ替え

【共通マクロ】
 指定範囲の取得
 図形番号の指定

2008年3月22日土曜日

第86回目 図形作成システムの更なる完成度を求めて(その3)

○第86回目 図形作成システムの更なる完成度を求めて(その3)

 今回は
 4.図形のその他の属性の取得
 5.図形のその他の属性により図形を修正
 6.図形情報の一括取得(コネクタ情報は除く)
 です。

 ある時、"図形のサイズ等を合わせる"処理をしていました。
 ほとんど気にせずにパラメータを指定していたのですが、何かの関係で、全部の図形をという指定になっていたようです。それで実行させたものですから、すべての図形が皆同じになってしまいます。せっかく、作り上げたのに、位置関係、コネクタは大丈夫ですが、大体の部分の作成処理は無駄になってしまいました。おそらく、IMEのオンオフ状態が関係していたのでしょう。
 そんな失敗から、4,5番の機能を考えました。
 これは、第84回の"図形のサイズ等を合わせる"をもとにするものです。
 すべての図形のその他の情報を取得してセルに書き込むというものです。この機能と、5の逆の機能を組み合わせれば、原状の復帰が可能となるのです。
 その他の情報としては、次のものです。

AA;図形の種類
AB;サイズ_幅
AC;サイズ_高さ
AD;ラインの太さ  ライン及びコネクタのみ
AE;実線・点線か  ライン及びコネクタのみ
AF;矢印_先頭    ライン及びコネクタのみ
AG;矢印_最後    ライン及びコネクタのみ
AH;内部の色    画像、ライン及びコネクタは除く
AI;透明度     画像、ライン及びコネクタは除く
AJ;フォント_種類  画像、ライン及びコネクタは除く
AK;フォント_サイズ 画像、ライン及びコネクタは除く
AL;文字配置_縦   画像、ライン及びコネクタは除く
AM;文字配置_横   画像、ライン及びコネクタは除く
AN;外枠有無     画像、ライン及びコネクタは除く
AO;回転       コネクタは除く
AP;パスネーム   対象外

 最後のパスネームは画像を張り付けた時の元の画像のあり場所です。しかしながら、この情報の取得はうまくいかないので、現在では対象外としています。
 (画像はエクセル内の取り込まれてしまうので、もとの場所が不要となることから、取得ができないのではないかと思います。この情報は別のところに、例えば欄外に保管すべきものなのでしょう)
 これらの情報は、図形のサイズ等と同じく、設定と取得が逆の関係になっています。
 また、取得は内部コードとなりますので、そのままセルに書き込みます。設定の時はその内部コードを記述すれば、図形に反映されます。
 注意すべきは、すべての図形にすべての情報があるとか限らないことです。情報が取得できなくて、エラーになってしまう場合があります。
 また、図形の種類はよくわからないので、図形の名前から判断しています。2003エクセルでは図形の名前が統一化されているものがありますので、取得はできません。
 更に、グループ化されている図形は一つの図形となっていまいますので、その情報からは復元できません。グループ化を解いて情報の取得をしてください。グループ化した図形に対して復元をかけるとエラーになります。回避する手段をしてください。何回か試行錯誤すればわかります。

 図形の種類
 これは困りました。つまり、図形の名前で、図形の種類がわかるものなのか、ということです。
 エクセル2003の場合は、多くの種類の図形名前がAutoshapeとなっていますので、これからは図形の種類の取得は出来ません。(他の手段がわからないので、現時点ではそう思っていますというという意味です)
 2007を優先にし、図形の名前の中に該当する文字列があるかで決めます。

 ※mm2(i)は図形の名前
temp1 = mm2(i)
If InStr(temp1, "角丸四角形") <> 0 Then z_syu = 1
If InStr(temp1, "円") <> 0 Then z_syu = 2
If InStr(temp1, "爆発") <> 0 Then z_syu = 3
If InStr(temp1, "円形吹き出し") <> 0 Then z_syu = 4
If InStr(temp1, "直線コネクタ") <> 0 Then z_syu = 5
If InStr(temp1, "Line") <> 0 Then z_syu = 5
If InStr(temp1, "右矢印") <> 0 Then z_syu = 7
If InStr(temp1, "正方形/長方形") <> 0 Then z_syu = 8
If InStr(temp1, "Rectangle") <> 0 Then z_syu = 8
If InStr(temp1, "フローチャート") <> 0 Then z_syu = 9
If InStr(temp1, "ホームベース") <> 0 Then z_syu = 10
If InStr(temp1, "山形") <> 0 Then z_syu = 11
If InStr(temp1, "右中カッコ") <> 0 Then z_syu = 121
If InStr(temp1, "左中カッコ") <> 0 Then z_syu = 131
If InStr(temp1, "右大カッコ") <> 0 Then z_syu = 122
If InStr(temp1, "左大カッコ") <> 0 Then z_syu = 132
If InStr(temp1, "中カッコ") <> 0 Then z_syu = 141
If InStr(temp1, "大カッコ") <> 0 Then z_syu = 142
If InStr(temp1, "カギ線コネクタ") <> 0 Then z_syu = 31
If InStr(temp1, "図") <> 0 Then z_syu = 32
If InStr(temp1, "Picture") <> 0 Then z_syu = 32
If InStr(temp1, "Group") <> 0 Then z_syu = 90
 ※図形の種類(番号)が12以上のものは、それだけでは図形が再現できない、または、既存の作成システムでは二段階に分けているので、アウトプットとしての図形の種類を系列化してする、という意味です。(大カッコと中カッコは後者の例です。前者の例はグループ化された図形です)

・サイズ_幅
・サイズ_高さ
・ラインの太さ  ライン及びコネクタのみ
 これは、設定と同じ内容ですので説明不要です。

・実線・点線か  ライン及びコネクタのみ
 実線の場合は、1となります(内部コード。以下同じ)
 点線の場合は、3となります

・矢印_先頭    ライン及びコネクタのみ
・矢印_最後    ライン及びコネクタのみ
 最初も最後も矢印有は2、無は1

・内部の色    画像、ライン及びコネクタは除く
 カラーコードは、ForeColor.SchemeColorでのものを取得します。

・透明度     画像、ライン及びコネクタは除く
・フォント_種類  画像、ライン及びコネクタは除く
・フォント_サイズ 画像、ライン及びコネクタは除く
 これは、設定と同じ内容ですので説明不要です。

・文字配置_縦   画像、ライン及びコネクタは除く
・文字配置_横   画像、ライン及びコネクタは除く
縦の上中下 -4160、-4108、-4107
横の左中右 -4131、-4108、-4152
 となっています。

・外枠有無     画像、ライン及びコネクタは除く
外枠有の時 -1、無の時 0
 となっています。

・回転       コネクタは除く
 角度(一周360°)が取得されます。
 2003では直線の回転はありません。
 反映はエラーになります。

・パスネーム   対象外
 図形は、エクセル内部に含まれてしまうので、元のパス名の取得は無理なようです。
 別に管理する必要があります。

 これらの情報の図形への反映は、逆のことをすればいい(これまで図形の属性として設定したことをやればいいのです)ので、それほど複雑ではないと思います。

 6.図形情報の一括取得(コネクタ情報は除く)
 これは、今までのマクロの積み上げです。サブルーチン化されているものを、次々に呼び出して処理を行うというものです。
 上のその他の情報以外にものとしては、テキストの情報、位置の情報、コネクタの情報があります。このうちコネクタに関する情報を除きました。
 コネクタの情報は、こちら側から与えるもののなので、最終的な確認など他の情報とは更新のタイミングが異なるのではないかと思っています。それゆえに一括取得からは除きました。
 この機能は、今での逆となりますが、一つだけ、"図形の種類の変更"には注意が必要です。
 しかしながら、この機能は、"図形の種類の変更"に含まれていますので、これをコピーするか、サブルーチン化して呼び出すかという。いずれかの方法となると思います。モジュールの中で同じ機能が二つ存在することになりますが、"コピーする"のほうが単純なので簡単ですね。
 "サブルーチン化して呼び出す"はできてからでもいいのではないでしょうか。まずは成果物を出すことのほうが優先ではないでしょうか。

2008年3月16日日曜日

第85回目 図形作成システムの更なる完成度を求めて(その2)

○第85回目 図形作成システムの更なる完成度を求めて(その2)

 続きです。
 3.図形番号の設定の改善
 この機能の目的は、飛び飛びの図形番号を指定できるようにするということです。
 今までは、全部の図形、一つの図形、ある番号からある番号までの図形のいずれかという指定の仕方しか出来ませんでした。
 一つの図形及びある番号からある番号までの図形を複数個指定できるようするものです。例えば、3.5-9.11.16.20-28とか指定します。
 この意味は、解説するまでもなく、3.5.6.7.8.9.11.16.20.21.22.23.24.25.26.27.28の図形を指定しているものです。
 複雑かなと思っていましたが。、意外とすっきりしていました。
 今までの機能では、
 3が入れば3と3
 5-9が入れば、5と9
 というのが出力されます。
 この機能をそのままにして、1.出てきた結果を格納し、2.必要なだけ繰り返す、という二つの機能を追加すればいいのでした。
 番号を格納する変数を、zz_no(200)としました。これはモジュール変数です。モジュールの最初に記述してください。
 この変数の中には、上の例では、3.5.6.7.8.9.11.16.20.21.22.23.24.25.26.27.28とうものが、順番に格納されます。zz_no(1)=3、zz_no(2)=5とかいうようにです。
 既存の機能での出力は、no1とno9となります。ですから
 for i= no1 to no9
  zz_no(i-no1+1) = i
 next i
 となります。
 これまの処理で何個(ii5)か格納されているので、正確には
  zz_no(ii5+i-no1+1) = i
 となります。

 頭に戻りまして、入力値を3とか5-9とかに切り分ける処理です。
 これも"."の位置を取得すればいいことになります。
 その位置の前の部分が、既存の処理の入力値となります。
 そして、次の回の処理には、その部分を除いたもので処理を続ければいいことになります。
 最初はいいのですが最後はどうなるでしょうか。実質的な最後は、"."がなくてヌルでないということになります。次の回の処理は、使った部分は捨てられますので、文字列はヌルになります。ここでループを出ることになります。
 入力値 3.5-9.11.16.20-28
 最初の切り出し 3。残りは、5-9.11.16.20-28
 次の切り出し 5-9。残りは、11.16.20-28
 次の切り出し 11。残りは、16.20-28
 次の切り出し 16。残りは、20-28
 次の切り出し 20-28。(この段階で"."はない)残りは、ヌル
 次の切り出し ヌルなのでループを抜ける。

 格納した図形の数(ii5)は、初期値が0で、各回の処理ごとの図形の数を加算していきます。各回の図形の数は、"no9-no1+1"となります。

 最初の部分は次のようになります。
 Do
'終了は、文字がない時
If z_no15 = "" Then Exit Do

p2 = InStr(z_no15, ".")
If p2 = 0 Then
z_no = z_no15 '最後の場合
z_no15 = ""
Else
z_no = Left(z_no15, p2 - 1)
z_no15 = Mid(z_no15, p2 + 1)
End If
z_no は既存の処理で使われる変数。
 【既存の処理】

 後の処理は、図形番号の格納ですが、つぎのようになります。
 For i = no1 To no9
  zz_no(ii5 + (i - no1 + 1)) = i
 Next i
ii5 = ii5 + (no9 - no1 + 1)
Loop
 最後に
zz_no_max = ii5 として最終的な図形の数を格納しておきます。
 ※zz_no_maxはモジュール変数です。

 すでに、図形番号の指定はサブルーチン化していますので、一つ修正すればよいことになります。しかし、今回は出力値が変わってきますので、サブルーチンの読み込んだマクロ側の修正が必要とあります。
 今までの出力値は、no1とno9でしたが、これからはzz_no(i)と zz_no_max です。
 ですから処理側では、今までは
 for i = no1 to no9
  ActiveSheet.Shapes(i).Select
  処理
 next i
 となっていましたが、今後は、
  for i=1 to zz_no_max
   j= zz_no(i)
  ActiveSheet.Shapes(j).Select
    処理
  next i
 となります。
 図形の削除など、逆から進むものもありますので注意願います。
 この場合は、一行目のステップが
  for i= zz_no_max to 1 step -1 となります。
 ※"no1 to no9"、"no9 to no1"、"no1"、"no9"などの文字列で、モジュール内の該当箇所を探してください。意外と修正漏れがあるものです。

2008年3月8日土曜日

○第84回目 図形作成システムの更なる完成度を求めて(その1)

○第84回目 図形作成システムの更なる完成度を求めて(その1)

 いろいろと仕事を実行していきますと、これも必要だということが次から出てきます。システムの完成度を高めるために、取り組まざるをなくなりました。
 今回のテーマは次のとおりです。

 1.図形のサイズ等を合わせる
 2.図形の回転
 3.図形番号の設定の改善
 4.図形のその他の属性の取得
 5.図形のその他の属性により図形を修正
 6.図形情報の一括取(コネクタ情報は除く)

 1.図形のサイズ等を合わせる
 ほかの図形をこの図形と同じようにしたいというニーズがあります。
 対象となるのは、サイズ、色、文字のフォント・サイズ・位置です。
 ここで、操作上の問題が出てきました。今までも潜在的にあったものですが、強調されてきました。
 それは、対象となる図形の番号が飛び飛びになっていますということです。最初からグループごとに並べるように設定しているのですが、順番が崩れてきます。これまでの機能を利用すると、図形番号の並べ替えの機能(第83回)を使えば番号が整理されるのですが、めんどくさいのおっくうになって利用していません。それよりも飛び飛びに番号が指定できるようにしたらどうか、という思いが強まりました。このテーマは次の次に取り上げます。
 "図形のサイズ等を合わせる"のマクロのポイントは、元の図形番号とコピーする図形番号の取得、属性の取得と設定です。今までやっていないのは、属性の取得ということです。
 元になる図形からサイズなどの属性をどう取得するか。試してみたら簡単でした。設定と取得の構文が裏腹の関係になっているだけなのです。
 例えば、サイズの設定は、
  Selection.ShapeRange.Height = hig2
Selection.ShapeRange.Width = wid2
 となっています。
 サイズの取得は、この式を逆にすればいいのでした。
hig2 = Selection.ShapeRange.Height
wid2 = Selection.ShapeRange.Width
他の属性も同じでした。

マクロの流れは、
1.元になる図形番号の設定(既存のもの)
2.元にするサイズ等の取得
3.コピーする図形番号の設定(既存のもの)
4.コピー先の図形のサイズ等の変更
 となりますが、入力と処理を分離して

1.元になる図形番号の設定(既存のもの)
2.コピーする図形番号の設定(既存のもの)
3.元にする図形のサイズ等の取得
4.コピー先の図形のサイズ等の変更
 とします。
 1.の後に、no_orgとして元にする図形番号を確保しておきましょう。

 3.元にする図形のサイズ等の取得は次の通りです。
 順番に縦サイズ、横サイズ、中の色、フォントの種類、フォントのスタイル、フォントのサイズ、文字の縦位置、文字の横位置となっています。
ActiveSheet.Shapes(no_org).Select
hig = Selection.ShapeRange.Height
wid = Selection.ShapeRange.Width
iro = Selection.ShapeRange.Fill.ForeColor.SchemeColor
fo_na = Selection.Font.Name
fo_sty = Selection.Font.FontStyle
fo_siz = Selection.Font.Size
ichi1 = Selection.VerticalAlignment
ichi2 = Selection.HorizontalAlignment

 属性の変更(設定)はこの逆になりますので、既存の"文字の変更"などを参照してみてください。

 2.図形の回転
 現在のシステムでは、大きな右向き矢印を作成できます。これを時と場合によっては、左向きとか、上向きとかに直したい場合が出てきます。これは図形の種類ではなく図形の回転で対応しようとするものです。
 左向きにするには180度の回転、上向きにするには270度の回転、下向きにするには90度の回転となります。
 方向性を持つ図形の場合には便利な機能です。水平の直線が斜め線などにが簡単に変わります。
 ここでその後の操作上の注意点があります。
 一つ目は、回転がかかった図形に更に回転をかけたい場合です。これは原型となる図形に戻ってもらって、指定すればいいことになります。左向きにするにはどんな回転になっていても、180度の回転となるということです。
 二つ目は、図形の縦横のサイズです。回転するとどうなってしまうのかということですが、縦横の大きさは最初の図形にくっつているということです。矢印を長くしたいとすると、原形の図形では横のサイズを大きくすることです。ですから、どのような向きになっても横のサイズを大きくするのです。

 回転のコマンドは至極単純です。
Selection.ShapeRange.Rotation = kaiten
 となります。
 また、コネクタに対しては回転はかけないようにしてください。

 ここまで。

2008年3月2日日曜日

第83回目 図形作成システムの完成度を求めて(その6)

○第83回目 図形作成システムの完成度を求めて(その6)

 今回は、残りました、
 1.図形番号の並べ替え
 2.図形のグループ化及び解除
 を取り上げます。

 まず、"2.図形のグループ化及び解除"です。
 グループ化とその解除のコマンドはどうなっているでしょうか。
 マクロの記録をとってみると、
 グループ化は、
ActiveSheet.Shapes.Range(Array(……)).Select)
で図形を指定して、
Selection.ShapeRange.Group.Select
 です。
 解除は、グループ化するとそのグループ群は図形としては一つとなりますので、その図形番号を選択して
Selection.ShapeRange.Ungroup.Select
 です。
 グループ化した場合、テキストの書き込みはできず、エラーとなります。当然取得もエラーとなります。注意してください。
 ここで更なる問題が発生しました。複数の図形の一括選択はすでに、"図形の整列"で行なっていたので大丈夫だと思ったのですが、ダミーで繰り返し図形を選択し続けるという、あのやり方ではダメだったのです。

 現象としてはこういうことです。
 図形番号の変数としては100個用意されています。
 3個の図形を選択したら、グループ化されたのは、2番目と3番目だけでした。
 4個の図形を選択したら、4つともグループ化されました。
 5個の図形を選択したら、エラーとなりました。
 7個の図形を選択したら、1番目と2番目の図形だけがグループ化されました。
 100個の変数を10個にしたら4個の場合でも全部はグループ化されませんでした。
 100個とか10個というのも絡んでいそうです。
 理由は?
 この現象から帰納的にしばらく考えてみました。
 3と100、1個のみ対象外。
 そういえば、100を3で割れば、1余るなあ。
 でも、4と5は両方とも割り切れる。でも結果が正反対。
 ということで、しばらく考えた結果、商もかかわりあがるということに気がつきました。
 わかると簡単です。array文で図形を選択するのですが、その数がわからないため、工夫として繰り返したのでした。その繰り返しの回数が鍵を握っていたのでした。まずは、選択、次は解除、その次は選択、その次は解除というふうになっていたようです。
 ですから、偶数回繰り返すと解除になってしまうのです。
 4個では大丈夫で、5個ではだめだった理由はここにあります。
 3個の場合は、33回目に選択した段階ですべてが選択されていました。次の1回で一番目が解除されたのです。そこで100個は終了したしましたので、2,3番目だけが有効となったのです。
 さてどうやってこれを解消しましょうか
 まず対応としては、繰り返すものをすべてではなく、第一番目の図形番号だけにします。すると被害は、一つの図形だけになります。また、確率は半々になります。
 したがって、二つのものを用意しておき、そのときの状況によって、どちらかを選択すればいいのです。
 全部を201個として、正味の選択する図形を例えば9とすると、繰り返し指定しなければならない回数は、201-9=192となります。この場合は、すでに選択していることから、偶数回は元に戻りますので、選択となります。よって、201個の指定のままでいいことになります。
 選択図形が10個だったらどうでしょうか。残りは奇数になります。この場合は、選択の解除となります。この場合は、200個までの指定にしておけばいいのです。200個までの指定では、偶数回の選択になりますので、9個の例と同じように、選択となります。
 ですから、とても長いArray文、201個のものと200個のものをつくり、条件によって選択すれば解決となります。
 長いコマンド文になりますが、コピー・修正を繰り返せがそれほどではなく出来上がります。継続行の指定は数の制限があるので、物理的な1行で20個記述することにしてください。
  ActiveSheet.Shapes.Range(Array( _
nn(0), nn(1), nn(2), nn(3), nn(4), nn(5), nn(6), nn(7), nn(8), nn(9), nn(10), nn(11), nn(12), nn(13), nn(14), nn(15), nn(16), nn(17), nn(18), nn(19) _
     :     :     :     :
, nn(180), nn(181), nn(182), nn(183), nn(184), nn(185), nn(186), nn(187), nn(188), nn(189), nn(190), nn(191), nn(192), nn(193), nn(194), nn(195), nn(196), nn(197), nn(198), nn(199), nn(200) _
)).Select
 というような感じです。
 後は注意すべき点はありません。

 1.図形番号の並べ替え です。
 やっとロジック系のマクロになりまた。
 ここでは番号の若いもの(新しい番号におけるもの)から、図形を一番前(図形番号では一番大きい)においていきます。全部終われば、一番最初に処理したものが一番後ろ(図形番号では一番小さい)になります。
 新しい番号体系(次の操作を前提とすれば連番である必要はない。しかしマクロを動かす時は、B列は連番であることが必須です)はB列に書き込まれているとします。C列は古い番号が書き込まれています。
【手作用により新しい番号体系を連番にする】
 1.BとC列を指定してB列順にソートします。
 2.A列に1からの連番を振ります。
 3.A-C列を指定して、C列順にソートします。
 4.A列をB列にコピーします。
 これでB列に連番の新しい番号がはいります。

 処理の考え方は次のようになります。
 1.B列から1番のものを探す。
 2.1番の図形番号(C列)を最前面(=図形番号が一番大きくなる=ii9となる)に移します
  (エクセルの内部では図形番号が自動的に更新されます。そのため3.の処理が必要となります)
 3.当該図形番号より大きい図形番号をマイナス1します。

 4.B列から2番目の図形を探す。
 5.2から4.の繰り返しです。
 変数としては、
n_old(200)…初めの図形番号
n_new(200)…並べ替えたい新しい図形番号
n_gen(200)…一回ずつ並べ替えた後、更新した図形番号
を設定します。
1.で判断する図形番号は、n_new(k)の中に入っているものです。添え字ではありません。
 3.で判断する図形番号は、n_gen(k)の中に入っているものです。添え字ではありません。
現在、新しい番号で何番目の図形を処理しているかを、iとします。
1.は、if n_new(j)=i となります。
2.は、n_gen(j)を最前面にします。あわせてn_gen(j)=ii9とします。
3.は、n_gen(j)より大きいn_gen(k)をマイナス1します。n_gen(k)=n_gen(k)-1
i=i+1として、繰り返しです。
最前面にするのは、おさらいですが、次のようになります。
ActiveSheet.Shapes(j).Select
Selection.ShapeRange.ZOrder msoBringToFront

余裕があれば、マクロの中で、B列の数値を順番に並べ替え、1からの連番にする機能を入れてください。
これはこんがります。いや、こんがりました。