2012年01月05日

関連記事: マクロのパスワードロックは駄目?

 マクロ ライブラリをパスワードロックした場合に、マクロ内に記述してある
日本語の文字が壊されてしまい、MsgBox や セル等に出力した際に文字化け
してしまうという問題があり、上記ページに幾つか回避策を紹介しています。
(1) セルから取得する日本語文字列は文字化けしない。
(2) ダイアログエディタで定義したラベル等の日本語文字列は文字化けしない。
(3) Basic コード内で【定数】として使用する日本語文字列は
    (a) 1文字なら chr 関数で記述する。
    (b) 長い日本語文字列は、パスワードロックしない別のライブラリを作成して、
         そこに日本語文字列取得関数を用意する。
(1) は「マイマクロ」 や 「拡張機能」 のマクロでは利用できません。
(3-a) は気の遠くなるような編集作業に二の足を踏みます。
(3-b) ではロック有り/ロック無しのライブラリを同梱する事への管理上の問題もあります。


これらよりも、かなり扱い易い回避策がありましたので紹介します。

     LibreOffice > ホーム > フォーラム > マクロとUNO API
    「ライブラリーをパスワードロックした場合のエラーと文字化けについて

ConvertToURL / ConvertFromURL 関数を利用して、マクロコード上では、UTF-8 エンコード
したものをコンスタントとして記述しておくというものです。

(Step-1)
日本語文字列を  ConvertToURL 関数を利用して UTF-8 エンコードする。
(作業ブックのセルに書き出しておく)
ThisComponent.getSheets.getByIndex(0).getCellRangeByName("A1").String _
= Mid(ConvertToURL("日本語") , 9)
ConvertToURL では 先頭に file:/// が付きますので、Mid関数で取り除いています。

(Step-2)
日本語文字列を出力するマクロ部分では、上記の UTF-8 エンコード文字列を
ConvertFromURL 関数で括って記述する。
MsgBox ConvertFromURL("%E6%97%A5%E6%9C%AC%E8%AA%9E")


【楽】とは言いませんが、かなり扱い易くはなりましたし、そのライブラリ内で完結させる
マクロ記述が可能になります。


お役に立ちましたら拍手して貰えると嬉しいです

addinbox at 15:04コメント(0)マクロ・関数トラブル・バグ 

2011年08月11日

( 関連記事 : OOo.Q&A [ faq4 ] リスト

本日、『 OpenOffice.org Q&A 』 が8月末をもって終了するとのアナウンス
faq/6/281 )が出されました。

長い間、運営お疲れ様でした & ありがとうございました。

幸い、9月以降でも【投稿の中止】のみであり、サイト自体は閉鎖しないという
事ですので、蓄えられたQ&Aの数々は今後も【閲覧オンリー】で利用できる
との事です。


分割作業が途中で止まっていた faq/4 カテゴリですが、これにより、現状での
分割状態で凍結になると思われます。

そこで、【OOo.Q&A [ faq4 ] リスト】ツールを修正しました。
Ver1.10 で施したチェックボックスによる [4a / 4b] [4] の選択を止め、IDの値で
自動的に以下のカテゴリで 表示するようにしました。
        [     1〜  150] ⇒ 4a
        [  151〜1000] ⇒
        [1001〜1150] ⇒ 4b
        [1151〜1819] ⇒

【OOo.Q&A [ faq4 ] リスト】 のダウンロードは こちら です。



お役に立ちましたら拍手して貰えると嬉しいです

addinbox at 15:03コメント(0)雑感 他 

2011年07月26日

【 関連記事 : INI ファイル操作関数

[ Open  Output ] ステートメントでは、存在しないファイル名を指定した場合、
そのファイル名で自動的にファイルが作成されます。

これは、VBAでも、OOo.Basicでも同じです。

ここで、そのファイルパスが【存在しないフォルダ】だった場合には、
どうなるでしょうか?

VBAでは「パスが見つからない」という実行時エラーになって失敗します。
当然、ファイルも作られません。


ところが、OOo.Basic では【存在しないフォルダ】も一緒に作成してくれます
【存在しないフォルダ】を作成した上で、その中に指定のファイルを作成
してくれます。


VBAでは、そこまでやってくれないので、『 SHCreateDirectoryEx 』というWin_APIを
利用してフォルダを作成する必要があります。

「INI 操作関数」の【OOo.Basic ⇒ VBA 逆移植版】では、この点に気付かないまま、
そのまま移植したので、その部分でバグがありました(現在、修正済)。







お役に立ちましたら拍手して貰えると嬉しいです

addinbox at 01:01コメント(0)マクロ・関数OOo に花丸♪ 

2011年04月19日

【 関連記事 : スピンボタンは【動的に作成】のみ
【        : スピンボタンの動的作成(その2)

上記記事で作成するスピンボタンですが、WindowsXP で
ウィンドウスタイルが「XPスタイル」の場合、ボタンの矢印が
変です。

SpinButtonBug1

・ 水平方向の場合、矢印が内向きになります。

・ 垂直方向の場合、下矢印に縞模様が出ます(ブルーとシルバーでも変わります)。

現在の最新版(OOo3.3.0)でも確認されています。
このバグは下記にて報告してあります。

[ Issue# 117891 ]


お役に立ちましたら拍手して貰えると嬉しいです

addinbox at 22:34コメント(0)ダイアログトラブル・バグ 

2011年02月06日

VBAには、所謂「構造体」を定義する『ユーザー定義型』というものがあります。
Type UserDefType1
  Item1 As String
  Item2 As Long
  Item3 As ・・・
End Type

Dim ABC As UserDefType1

MsgBox ABC.Item1

OOo.Basic のヘルプには、この「Type ステートメント」が載っていませんが、
試してみると使えることが判ります。

使えることは使えますが、使う上で非常に注意しなければならない問題があります。

それは、
      「ユーザー定義型」変数同士の代入は【代入元への参照の引渡し】
だという事です(要素同士での値代入ではなく、構造体全体での代入)。
Dim ABC As UserDefType1
Dim XYZ As UserDefType1

XYZ = ABC    '構造体同士の代入では参照渡しになってしまう

XYZ.Item1 = ABC.Item1  '要素同士での代入ならば問題なし
XYZ.Item2 = ABC.Item2

サブルーチン/関数での引数でいえば【 ByRef 】動作に当たります。

つまり、代入元の値を変更すれば、同時に代入先変数の内容も変わります。
逆に、代入先の値を変更しても、同時に代入元変数の内容が変わります。

下記マクロを試せば、この意味が判ります。
Type TestType
  aa1 As string
  aa2 As string
  aa3 As Integer
End Type

Sub Main1()
Dim Base1(1 to 3) As TestType
Dim Base2 As TestType
Dim Copy1 As TestType
Dim Copy2 As TestType

Base1(1).aa1 = "[Ary1] "
Base1(1).aa2 = "QWERTYU"
Base1(1).aa3 = 9876

Base1(2).aa1 = "[Ary2] "
Base1(2).aa2 = "ABCDEFG"
Base1(2).aa3 = 12345

Base1(3).aa1 = "[Ary3] "
Base1(3).aa2 = "poiuyt"
Base1(3).aa3 = -345

Base2.aa1 = "[NonAry] "
Base2.aa2 = "mnbvc"
Base2.aa3 = 2745

'===================================
Copy1 = Base1(2)
Copy2 = Base2

msgbox "---- [Base]を[Copy]へコピー ----" & chr(13) & chr(13) & _
       Base1(1).aa1 & " , " & Base1(1).aa2 & " , " & Base1(1).aa3 & chr(13) & _
       Base1(2).aa1 & " , " & Base1(2).aa2 & " , " & Base1(2).aa3 & chr(13) & _
       Base1(3).aa1 & " , " & Base1(3).aa2 & " , " & Base1(3).aa3 & chr(13) & _
       Base2.aa1 & " , " & Base2.aa2 & " , " & Base2.aa3 & chr(13) & chr(13) & _
       Copy1.aa1 & " , " & Copy1.aa2 & " , " & Copy1.aa3 & chr(13) & _
       Copy2.aa1 & " , " & Copy2.aa2 & " , " & Copy2.aa3

'===================================
Base1(2).aa2 = "*****"
Base1(2).aa3 = 5432
Base2.aa2 = "+++++"
Base2.aa3 = -475

msgbox "---- [Base]データを変更 ----" & chr(13) & chr(13) & _
       Base1(1).aa1 & " , " & Base1(1).aa2 & " , " & Base1(1).aa3 & chr(13) & _
       Base1(2).aa1 & " , " & Base1(2).aa2 & " , " & Base1(2).aa3 & chr(13) & _
       Base1(3).aa1 & " , " & Base1(3).aa2 & " , " & Base1(3).aa3 & chr(13) & _
       Base2.aa1 & " , " & Base2.aa2 & " , " & Base2.aa3 & chr(13) & chr(13) & _
       Copy1.aa1 & " , " & Copy1.aa2 & " , " & Copy1.aa3 & chr(13) & _
       Copy2.aa1 & " , " & Copy2.aa2 & " , " & Copy2.aa3

'===================================
Copy1.aa2 = "%%%%%%"
Copy1.aa3 = 683
Copy2.aa2 = "$$$$$$"
Copy2.aa3 = -812

msgbox "---- [Copy]データを変更 ----" & chr(13) & chr(13) & _
       Base1(1).aa1 & " , " & Base1(1).aa2 & " , " & Base1(1).aa3 & chr(13) & _
       Base1(2).aa1 & " , " & Base1(2).aa2 & " , " & Base1(2).aa3 & chr(13) & _
       Base1(3).aa1 & " , " & Base1(3).aa2 & " , " & Base1(3).aa3 & chr(13) & _
       Base2.aa1 & " , " & Base2.aa2 & " , " & Base2.aa3 & chr(13) & chr(13) & _
       Copy1.aa1 & " , " & Copy1.aa2 & " , " & Copy1.aa3 & chr(13) & _
       Copy2.aa1 & " , " & Copy2.aa2 & " , " & Copy2.aa3
End Sub


これと同じ問題は配列変数同士の代入にも見られます。
  参照 : 【大問題】 配列変数の代入はリンクだった!

配列の場合には、基本的に「代入後に [ReDim Preserve] を実行する」という対策で
回避できましたが、ユーザー定義型には当然 ReDim などは使えません。

ユーザー定義型では、「関数内の局所変数で要素同士の代入」を経由する方法を
採る必要があります。
'============= (NG)
Function CopyTestType1(arg1 As TestType) As TestType
'直接代入と同じで[参照]が引き渡されるだけになります。
  CopyTestType1 = arg1
End Function

'============= (NG)
Function CopyTestType2(arg1 As TestType) As TestType
'これは実行時エラーになります。
'関数の返却値領域として、関数定義時には[TestType]属性が反映されていない為?
  With CopyTestType2
    .aa1 = arg1.aa1
    .aa2 = arg1.aa2
    .aa3 = arg1.aa3
  End With
End Function

'============= (OK)
Function CopyTestType3(arg1 As TestType) As TestType
'要素ごとの【値 代入】を行ない、且つ、局所変数で新たな領域を確保しているので、
'返却されるデータはコピー元(引数)とは別個のデータ領域となります。
'局所変数は、関数が実行される度に確保し直されるので、
'関数を経由する度に新たなデータ領域としてコピー可能です。
Dim Temp1 As TestType
  With Temp1
    .aa1 = arg1.aa1
    .aa2 = arg1.aa2
    .aa3 = arg1.aa3
  End With
 
  CopyTestType3 = Temp1
End Function
上記マクロを追加して
Copy1 = Base1(2)
Copy2 = Base2
の部分を
'直接代入 ・・・ 参照になる(NG)
Copy1 = Base1(2)
Copy2 = Base2

'関数を経由して代入1 ・・・ 参照になる(NG)
Copy1 = CopyTestType1( Base1(2) )
Copy2 = CopyTestType1( Base2 )

'関数を経由して代入2 ・・・ (これは実行時エラーになります)
Copy1 = CopyTestType2( Base1(2) )
Copy2 = CopyTestType2( Base2 )

'関数内の[局所変数]経由で代入 ・・・ [値]代入になり問題なし(OK)
Copy1 = CopyTestType3( Base1(2) )
Copy2 = CopyTestType3( Base2 )
に変えて、各々の処理結果を試してみてください。


ユーザー定義型を幾つも使っている場合には、下記の雛形を修正して使えば、
関数はひとつで済みます。
'ユーザー定義型のデータコピー汎用関数[雛形]を使用
Copy1 = CopyUserDefType( "TestType", Base1(2) )
Copy2 = CopyUserDefType( "TestType", Base2 )

'ユーザー定義型のデータコピー汎用関数[雛形]
Function CopyUserDefType(argTypeName As String, argTypeData As Variant) As Variant
Dim Temp1 As TestType
Dim Temp2 As xxxxType
'     :

  Select Case UCase(argTypeName)
    Case "TESTTYPE"
      With Temp1
        .aa1 = argTypeData.aa1
        .aa2 = argTypeData.aa2
        .aa3 = argTypeData.aa3
      End With
      CopyUserDefType = Temp1

    Case "XXXXTYPE"
      With Temp2
        .bb1 = argTypeData.bb1
        .bb2 = argTypeData.bb2
      End With
      CopyUserDefType = Temp2

'    Case ......
'      ......

    Case Else
      CopyUserDefType = Nothing
  End Select
End Function

とはいえ、Type ステートメント/ユーザー定義型は、ヘルプにも正式には載せて
いない機能ですから、使わずに済むのであれば、使わない方向でマクロを
作成した方が良いでしょう。



お役に立ちましたら拍手して貰えると嬉しいです

addinbox at 12:39コメント(3)マクロ・関数トラブル・バグ 
記事検索
livedoor プロフィール



  • ライブドアブログ