2012年9月30日日曜日


 
○第167回目 計算式中の一部を置換え

 
 計算式をコピーしたり、移植したあとに、置き換える必要があります。その際のマクロとして、複数項目の置換えがあるのですが、それは、別のセルに置換情報を入れる必要があります。ここを改善したものを作ろうという趣旨です。

 計算式の取得=⇒計算式の中から置換え前文字列を選ぶ=⇒これに対応した置換え後文字列を作る=⇒これらを繰り返す=⇒すべての指定が終了した後=⇒置き換え範囲を指定して計算式を置き換える。

 という流れです。置換え前文字列を作るという操作が不要となりますし、置き換え後のもの作る時の手間が若干簡素化されます。

 

 1.計算式の取得

 2.計算式の中から置換え前文字列を抜き出す(不要な文字列を削除する)

 3.これに対応した置換え後文字列を作る

 =⇒これらを繰り返す。最大21項目

 4.置き換え範囲を指定

 5.計算式を置き換える。

'置換え処理。置換え文字列の数だけ繰り返す

  Range(Cells(gyo1, retu1), Cells(gyo9, retu9)).Select

  For i = 0 To rep_cnt - 1

    Selection.Replace What:=rep_moji1(i), Replacement:=rep_moji2(i), LookAt:=xlPart, _

    SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _

    ReplaceFormat:=False

  Next i

 

 

 計算式が長い場合があるので、フォームのテキストボックスを使用します。
 ※フォームについては、『○第133回目 計算式作成のお手伝い(一般的な計算式、究極モドキ3)』を参照。

 
 コピーしたとき、不要な他のブック等の情報が入った計算式も、このマクロで簡単に直せます。

 問題は計算式の条件(警察の形式を満たしていない、参照先がないなど)を満たさない時、逐一聞いてくることでしょう。大量に置換える場合は、ためしの処理が必要でしょう。

 

 

 

 

2012年9月29日土曜日

○第166回目 シート名一括変更

 シート名を一括変更しようとするマクロです。
 シート名変換表を作って、それをもとに一気に変更しようというものです。
 既存のシート名の取得は、すでに作ってあるマクロで行います。それで変更前のシート名一覧を取得(シートに出力)しておきます。(『○第35回目 エクセルのファイルを分析する』参照)

 シート名変換表といってもいろいろなイメージがあると思いますが、ここでは二つのパターンを考えて見ます。
 1.シート番号、空セル、変更後のシート名 の3列で指定
 2.変更前のシート名 変更後のシート名 の2列で指定
 1.と2.の違いは、指定した列の数が3列か2列かで判定します。
 また、いつも一覧表のすべてを変更するということもないと思われますので、変更後のシート名がないものは、変更しないものとします(変更しないものを削除して詰めた形の変換表でもかもいません)。
 
 
    手順です。
 1.変換表の場所を取得する
 2.全シート名を取得する
 3.シート名で指定するものは、シート名を比べながら、変更すべきシートの番号を取得します。シート番号で指定するものは、その番号を使います。
 4.シート名を変更します。

 ポイントとは、次のとおりとなります。
'シート名の取得
  cc = Sheets.Count 'ブックにおけるシートの枚数
  If cc > 100 Then cc = 100 'とりあえず100シートを限度としています。
  For i = 1 To cc  'ワークシートの数だけ繰り返す
   ww(i) = Sheets(i).Name '取得したシート名を取得する
  Next i

 '変更すべきシート番号の取得とシート名の変更
 For i = 0 to gyo_cnt - 1
  If Cells(gyo1 + i, retu1 + retu_cnt - 1) <> "" Then '変更後が空セルの場合は処理しない
   If retu_cnt = 2 Then '変更前のシート名に基づき変更する場合
'変更元のシート番号の取得
    For ii = 1 to cc
     If Cells(gyo1 + i, retu1) = ww(ii) Then Exit For 'シート名と同じ番号を取得する
    Next ii
    sheet_no = ii
   Else 'シート番号に基づき変更する場合
    sheet_no = Cells(gyo1 + i, retu1)
   End If
   If sheet_no <= cc Then
'シート名の変更
    Sheets(sheet_no).Name = Cells(gyo1 + i, retu1 + retu_cnt - 1)
   End If
  End If
 Next

 1個とか2個の修正の場合は、通常操作のほうがいいでしょうね。
 
 
 
 

2012年9月28日金曜日

○第165回目 エクセルマクロの基本コマンド

 エクセルマクロの基本コマンドは何か、というものです。
 基本とは、結構、頻繁に使われるというコマンド群をさします。
 これさえあれば、骨格の70%はできるというものです。


┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 初心者の方へ
┃ 以下のそれぞれのマクロ(□以下に書かれているもの。不適
┃なものもある。)を、モジュールに貼り付けて、デバックして
┃、それぞれの変数にどのような数値がはいるのか試してくださ
┃い。変数の初期値はゼロなので、うまく動かないものもありま
┃す。
┃ マクロのイメージが少し分かります。
┃ ・エクセルのマクロの世界への移行。=⇒エクセルシートに
┃いて、Alt+F11を押す。+は同時押しの意味です。すなわち、Al
┃tとF11を同時に押す。
┃ ・(以下はマクロの世界での操作)モジュールシートを作る=
┃⇒Alt、I、M(この場合は逐次押しで良い)
┃ ・(以下はモジュール上での操作)"sub test01()" を貼り付
┃ける。自動的に、"End Sub"が付加される。
┃ ・Sub test01()とEnd Subの間に、以下のマクロを貼付ける。
┃ ・F8を押すと色のついたマクロ行が1行ずつ実行される。
┃ ・処理後のマクロ行の変数にカーソルを置くと、その変数の
┃ ・処理後のマクロ行の変数にカーソルを置くと、その変数の
┃内容が表示される。つまり、そのマクロ行の処理内容がわかる
┃ ・一気に処理を進めたい場合は、任意のマクロ行にカーソル
┃を移し、Ctrl+F8を押す。そこまで処理が一気に進む。
┃  End Subにカーソルを置き、Ctrl+F8を押すと、終了直前の
┃状態になる。この状態でも変数の内容の確認ができる。
┃ ・モジュールを削除する(必要な場合(モジュールつきのブッ
┃クを保存する場合、拡張子を変更する必要があるので、気持ち
┃が悪いという人の場合))=⇒画面左上のプロジェクトウィンド
┃ウのmodule1などを右クリックし、モジュールの解放を選択。
┃保存の有無が聞かれるが、保存してもしなくても良い。
┃ ・エクセルの世界へ戻る=⇒Alt+F11を押す。
┃ ・エクセル2010の場合、モジュール付きのブックを登録する
┃時は、拡張子を"xlsm"にする必要があります。
┃ ・おまけ。以下は完結したマクロです。これも貼り付けで試
┃してみてください
┃  Sub 和を求める()
┃   '数値の指定
┃    Suuti = InputBox("数値を入れてください。", , 10) 
┃                                                       
┃    kotae = 0
┃    For i = 1 To Suuti Step 1
┃      kotae = kotae + i
┃    Next
┃    MsgBox ("1から" & Suuti & "まで加算した答えは、" &
┃ kotae & "です。")

┃    End Sub
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛



□実行時のブック(ファイル)の属性(ぶっく名、シートの属性)の取得
    fname1 = ActiveWorkbook.Name
    shname1 = ActiveSheet.Name
    ii_max = Sheets.Count
    ii0 = ActiveSheet.Index
 

□実行時のセルの指定範囲の情報の取得
 ''範囲情報の取得
    AAA = Selection.Address
    gyo1 = Selection.Row
    gyo_cnt = Selection.Rows.Count
    gyo9 = gyo1 + gyo_cnt - 1
    retu1 = Selection.Column
    retu_cnt = Selection.Columns.Count
    retu9 = retu1 + retu_cnt - 1
    AAA11 = Cells(gyo1, retu1).Address
    AAA9 = Cells(gyo9, retu9).Address
 

□シート名の取得
'シート名の取得
    Dim p_mm0(100)
    cc = Sheets.Count
    For i = 1 To cc   'ワークシートの数だけ繰り返す
       p_mm0(i) = Sheets(i).Name '取得したシート名を取得する
    Next i
 

□(例えば、設定された)範囲のセル群から値を取得
    Dim atai(100,110)
    for i = 1 to gyo_cnt
      for j = 1 to retu_cnt
        atai(i,j) = Cells(4 + i - 1, 3 + j - 1).Value
      next
    next
  

□(例えば、設定された)範囲のセル群から計算式を取得
 '計算式の取得
    Dim shiki(100)
    for i = 1 to gyo_cnt
        If Cells(4 + i - 1, 3).HasFormula = True Then
           shiki(i) = "xxx" & Cells(4 + i - 1, 3).Formula
        Else
           shiki(i) = ""
        End If
    next
 

□ブック、シートの指定
    Windows(fname1).Activate 'ブック名
    Sheets(ii0).Select 'シート番号
    Sheets(shname1).Select 'シート名
   
□セルの指定
    Range(AAA).Select  'AAAには、"A5"、"B5:B10"などの座標が入っている。
   Cells(4, 3).Select
   Range(Cells(4, 3),Cells(10, 6)).Select
 

□コピー
    Dim b_name(100)
    Windows(fname1).Activate '現在のブックであれば省略可能
    Sheets(ii0).Select '現在のシートであれば省略可能
    Range(Cells(4 , 3 ), Cells(10, 6)).Select
    Selection.Copy

    Windows(b_name(bk_no)).Activate '現在のブックであれば省略可能
    Sheets(h2).Activate '現在のシートであれば省略可能
    Cells(24, 23 + cc).Select
    Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
      False, Transpose:=False
 

'計算式
    Selection.PasteSpecial Paste:=xlPasteFormulasAndNumberFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False


'数値と数値の書式
    Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
 

'列幅
    Selection.PasteSpecial Paste:=xlPasteColumnWidths, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
 

'書式
    Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
 

'リンク貼付け
    Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
    ActiveSheet.Paste Link:=True
 

'縦横変換コピー。値及び数値書式のみ
    Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
 

□セルに数値を書きだす
    Cells(4 + i - 1, 3 + j - 1) = atai
  

□セルに計算式を書きだす
    Cells(4 + i - 1, 3 + j - 1) = atai '=から始まっている文字列
 

□画面から入力
    h1 = InputBox("飛び先のシート番号を入れてください。 そのままのシートの場合は、0。-1,*1も可" & vbCrLf ,, 1)

□画面に出力
  Suuti = 10
  kotae = 55
  MsgBox ("1から" & Suuti & "まで加算した答えは、" & kotae & " です。")

□セルの座標の入力1(画面から)
  Dim セ As Range
  Set セル範囲 = Application.InputBox(Prompt:="次のセット範囲の先頭のセルを指定してください", Default:=AAA1, Left:=10, Top:=2, Type:=8)
 aaa2 = セル範囲.Address

'      Type:=の値 意味
'      0 数式
'      1 数値
'      2 文字列(テキスト)
'      4 論理値(TrueまたはFalse)
'      8 セル参照(Rangeオブジェクト)
'     16 エラー値(#N/Aなど)
'     64 数値配列

□セルの座標の入力2(画面から)
  Dim せる範囲 As Variant
'セルの設定
  in_rrcc01 = "C4"
  せる範囲 = Application.InputBox(Prompt:="使用するセルを指定してください。終了はキャンセルキー。", Default:="=" & in_rrcc01, Left:=10, Top:=2, Type:=0)
  If せる範囲 = False Then errflag = 0: Exit Do
'セルの座標をA1形式にするための処理
  in_rrcc2 = Application.ConvertFormula(Formula:=せる範囲, _
  FromReferenceStyle:=xlR1C1, ToReferenceStyle:=xlA1, ToAbsolute:=xlAbsolute)
  in_rrcc2 = Mid(in_rrcc2, 2)
  Range(in_rrcc2).Select
  gyo21 = Selection.Row
  retu21 = Selection.Column
 

□計算式の入力(画面から)
  Dim せる範囲 As Variant
  in_rrcc01 = "C4"
  keisansikin = Application.InputBox(Prompt:="計算式を入力してください。終了はキャンセルキー。", Default:="=" & in_rrcc01, Left:=10, Top:=2, Type:=0)
 

□時間の取得、処理時間の算定
   t10 = Time
   t9 = Time
   Cells(p1 + pp1, 3) = " 終了時間は、" & Application.WorksheetFunction.Text(t9, "hh:mm:ss") & "です。": pp1 = pp1 + 1
   Cells(p1 + pp1, 3) = " 処理時間は、" & Application.WorksheetFunction.Text(t9 - t10, "hh:mm:ss") & "です。": pp1 = pp1 + 1
 

□連続してセルに出力(下方向)するときの工夫
  pp1 = 3
  p1 = pp1 + 1: pp1 = 0
  Cells(p1 + pp1, 3) = " 終了時間は、" & Application.WorksheetFunction.Text(t9, "hh:mm:ss") & "です。": pp1 = pp1 + 1
  Cells(p1 + pp1, 3) = " 処理時間は、" & Application.WorksheetFunction.Text(t9 - t10, "hh:mm:ss") & "です。": pp1 = pp1 + 1
  Cells(p1 + pp1, 3) = " 処理レコード数は、" & Str$(jj_cnt) & "件です。": pp1 = pp1 + 1
  Cells(p1 + pp1, 3) = " 出力件数は、" & jj_cnt2 & "件です。": pp1 = pp1 + 1
 

□inputboxを使用したメニュー表示
  Dim b_name(100)
  bk_no = InputBox("使用したいブックを指定してください。そのままは0。そのままのシートの場合は、99。 " & vbCrLf & _
    "終了はキャンセルキー。" & vbCrLf & _
    "01=⇒" & b_name(1) & vbCrLf & "02=⇒" & b_name(2) & vbCrLf & _
    "03=⇒" & b_name(3) & vbCrLf & "04=⇒" & b_name(4) & vbCrLf & _
    "05=⇒" & b_name(5) & vbCrLf & "06=⇒" & b_name(6) & vbCrLf & _
    "07=⇒" & b_name(7) & vbCrLf & "08=⇒" & b_name(8) & vbCrLf & _
    "09=⇒" & b_name(9) & vbCrLf & "10=⇒" & b_name(10) & vbCrLf & _
    "11=⇒" & b_name(11) & vbCrLf & "12=⇒" & b_name(12) & vbCrLf & _
    "13=⇒" & b_name(13) & vbCrLf & "14=⇒" & b_name(14) & vbCrLf & _
    "15=⇒" & b_name(15) & vbCrLf _
    , xpos:=2000, ypos:=3000, Default:=99)
' ※vbCrLfは改行のこと

□画面の抑止・解放
'画面を止める
Application.ScreenUpdating = False
'画面を更新する
Application.ScreenUpdating = True
 

□自動計算の抑止・解放
'再計算を停止
    With Application
        .Calculation = xlManual
    End With
'再計算を実施
    With Application
        .Calculation = xlAutomatic
    End With
 

□エラーになった場合の処理(エラーになった場合、次の行の処理をする)
    On Error Resume Next
 

□エラーになった場合の処理(エラーになった場合、特殊な処理をする)
  On Error GoTo ErrorTrap
 
  ErrorTrap:
    errflag = 99
    Resume Next


2012年9月27日木曜日

○第164回目 パラメータを繰り返し入れて、結果を一挙に求める

 ある関数(かなり複雑なものを想定。関数というよりエクセルの計算システムというのが適切か)があり、その中の一パラメータをいろいろと変えていき、その関数値を求める。これを一挙に行い、その結果を一覧表にしようというもの。
 例
 計算結果=関数(項目1、項目2、項目3、項目4、項目5)(簡単な例で、関数=ax^2+bx+c として、xにいろいろな値をいれていき、答えを求める。=⇒この例だとマクロを使う必要はありませんね)
 出力例
 パラメータ 計算結果 最初の計算結果との差
 
 パラメータを変えた場合、どのような結果になるかというシミュレーションというイメージでしょうか。
 また、一意的に解けない方程式があり、ニュートン法でその答えの範囲を徐々に絞っていき、最終的な答えを求めるという場合にも利用(間接的に)できますね。
 ※ニュートン法=⇒複雑なので(というより、筆者が理解できないので、筆者の分かる範囲で)、簡単にいうと、一変数で成り立つ方程式=aを満たす、未知数を求める場合、方程式-a=0とみて、未知数の値をいろいろと入れていくことで、答えを求めようとするもの。
 未知数に、nを入れた場合、式の左辺がプラスになったとする。また、mを入れたときにマイナスになったとすると、答えはnとmの間にあると推測される。
 そこでnとmの間に適当(ちょうど真ん中でもいい)な値m1をとってみると、その答えが、プラスであれば、求める答えは、m1とmの間にあると思われる。また、マイナスであれば、求める答えは、nとm1のあいだにあると思われる。これを繰り返していくことによって、求める答えの範囲が狭まってくる。後は必要とする精度により、適当に求める範囲を絞り込めば良い。
 (この例での活用としては、nとmの間を10等分したものを入れて答えを求める。その結果の符号の変化で最終的に求めたい答えのある区間がわかる。これを繰り返す。)
 
 それでは手順です。
 0.パラメータは、変えたい値ではなく、もととなる値からの差の値とする。このくらい増えたらとか、このくらい減ったらという意味合いの数値を入れていく。
 新しい数値=元の数値 + パラメータ
 パラメータとして、1以下の小数の値を入れた場合は、増減率として考えて計算するという機能を追加するといいかもしれません(5%増とか、5%減とかいうイメージ)。
 新しい数値=元の数値*(1+パラメータ)

 1.複数のパラメータを入れてあるセルの範囲を指定してから実行(先頭のセルのみを指定し、パラメータは下にあるものとし、ヌルが出てきたのところで終了とする方法もある)
 2.パラメータによる新しい値を入れたいセルを指定する
 3.計算結果(答えでもあり、答えの初期値でもある)のあるセルを指定する
 4.パラメータの横に、そのパラメータによる結果(答え)及び基準値との差を入れて、一覧表を作成する。
 5.2.を実行前の値(初期値)に戻す。

 更なる機能としては、無条件に罫線でかこってしまうということも考えられます。
 また、結果表の範囲の座標を打ち出し、範囲印刷につなげるということも考えられます。


 マクロ作成に必要な機能
 1.Cellsコマンドによるパラメータの取得
    for i = 1 to gyo_cnt
       変数1(i) = Cells(gyo0 + i - 1, j)
    next

 2.3.セルの座標の指定(inputメソッドによるカーソル等を使ったセルの指定)
    Dim セル範囲 As Range
  Set セル範囲 = Application.InputBox(Prompt:="次のセット範囲の先頭のセルを指定してください", Default:=AAA1, Left:=10, Top:=2, Type:=8)
  aaa2 = セル範囲.Address

      Type:=の値 意味
      0 数式
      1 数値
      2 文字列(テキスト)
      4 論理値(TrueまたはFalse)
      8 セル参照(Rangeオブジェクト)
     16 エラー値(#N/Aなど)
     64 数値配列

 4.Cellsコマンドによる値の出力
    for i = 1 to gyo_cnt
    Cells(gyo0 + i - 1,retu0) = 変数1(i)
    Cells(gyo0 + i - 1,retu0+1) = 変数2(i)
    Cells(gyo0 + i - 1,retu0+2) = 変数3(i)
    next

 ※罫線の設定。全体座標の取得と打ち出し