インストールレスプログラミング( ´ー`)

VBA , JavaScript , HTAなど 365アプリはインストール必要ですが、仕事に無いケースはほぼないから(・_・;)

連続数字を表に入れるときのメモ

データを文字列を介していろいろな形に加工するという作業をよくやります。

わかってしまえば,たやすい事なんですが,思いつかないとしばらく悩まないといけないポイントがあり,

見事にはまった後解決した記憶がありましたので,たぶん多くの方にはつまんないことですが,メモとして書きます。




1,2,3,4,5,6,7,8,9,10,11,12,13,14,15


  ↓ 5列の表にしたい

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

こういうことをやりたいことがあるんです。けっこう頻繁に。。


商と余りを使えばいい。

とても簡単なんですが,元の数字をそのまま商と余りで処理しようとすると,意外に難しいことになります。

1 2 3 4
5 6 7 8 9
10 11 12 13 14
15

わたしみたいにあんまり物を考えない人はごり押しします。If文でごりごり書き出したり,

do loopなどでカウンタを条件に合わせてリセットすることで対処したり。。

(;´▽`A``ホントコマッタモノデス。


さて,引っ張りすぎですね。答えは簡単

0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

0から始まる数値なら,5で割り算をした商と余りを用いれば

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 0 0 0 0 1 1 1 1 1 2 2 2 2 2
余り 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4

きれいにできあがります。
気づいた時の自分に対するあきれようはすごいですが,しばらくするとすぐ忘れるモノデス(;´▽`A``

さて,パワーポイントのVBAをだいぶ忘れているので,思い出すためにパワーポイントのVBAコードで試します。

f:id:chemiphys:20170410224414p:plain
パワーポイントのスライド1に3つの表をこのSSのように並べます。それぞれに付けた名前はマクロで使用します。
場所や大きさは適当ですが,列数は守る必要があります。または,コードのほうを好きに変えるのもいいですね。

標準モジュールはこちら

Sub test()
    
    Dim TargetSlide As Slide: Set TargetSlide = ActiveWindow.View.Slide
    
    Dim SourceTable As Table: Set SourceTable = TargetSlide.Shapes("元表").Table
    Dim PasteTable As Table: Set PasteTable = TargetSlide.Shapes("貼付表5列").Table
    Dim PasteTable2 As Table: Set PasteTable2 = TargetSlide.Shapes("貼付表3列").Table
    
    Dim DataCollection As Collection: Set DataCollection = New Collection
    
    Dim r As Cell
    For Each r In SourceTable.Rows(1).Cells
        DataCollection.Add r.Shape.TextFrame.TextRange.Text
    Next
    
    Dim i As Long, tmp As String
    For i = 0 To DataCollection.Count - 1
        tmp = DataCollection(i + 1)
        PasteTable.Cell(Int(i / 5) + 1, i Mod 5 + 1).Shape.TextFrame.TextRange = tmp
    Next
    
    For i = 0 To DataCollection.Count - 1
        tmp = DataCollection(i + 1)
        PasteTable2.Cell(Int(i / 3) + 1, i Mod 3 + 1).Shape.TextFrame.TextRange = tmp
    Next

End Sub

実行すると,
f:id:chemiphys:20170410224645p:plain

このとおりです。

コードの補足を少しします。

    Dim TargetSlide As Slide: Set TargetSlide = ActiveWindow.View.Slide

対象のスライドからオブジェクトの指定が始まることがほとんどなので,対象のスライドをオブジェクト変数に入れます。
いろいろな方法がありますが,アクティブなスライドを捕まえる書き方の一つです。imihitoさんから教えていただいたヤツデス。

    Dim SourceTable As Table: Set SourceTable = TargetSlide.Shapes("元表").Table
    Dim PasteTable As Table: Set PasteTable = TargetSlide.Shapes("貼付表5列").Table
    Dim PasteTable2 As Table: Set PasteTable2 = TargetSlide.Shapes("貼付表3列").Table

表に名前がついているように感じますが,パワーポイントの場合いろいろなものはShapeオブジェクトとして扱われます。
各Shapeオブジェクトの中のTable のように指定するわけです。

    Dim DataCollection As Collection: Set DataCollection = New Collection

要素数を決めないで値を放り込むのに使えるということで,Collectionを使いました。配列を使ってもいいかもしれません。

    Dim r As Cell
    For Each r In SourceTable.Rows(1).Cells
        DataCollection.Add r.Shape.TextFrame.TextRange.Text
    Next

パワーポイントの表については,For Eachステートメントはとても使いにくいんですが,
Rowオブジェクト,Columnオブジェクト内にはCellsコレクションがあるので,そこを利用すれば強引にFor Eachが使えます。
二回 For Eachを使えば表全体を扱えるということですね。

    Dim i As Long, tmp As String
    For i = 0 To DataCollection.Count - 1
        tmp = DataCollection(i + 1)
        PasteTable.Cell(Int(i / 5) + 1, i Mod 5 + 1).Shape.TextFrame.TextRange.Text = tmp
    Next
    
    For i = 0 To DataCollection.Count - 1
        tmp = DataCollection(i + 1)
        PasteTable2.Cell(Int(i / 3) + 1, i Mod 3 + 1).Shape.TextFrame.TextRange.Text = tmp
    Next

それぞれの表に流し込んでいます。
表のセルは (1,1) ~ なので, 0を利用していることから1を足して利用しています。
Int(i/5)で 5で割った商 , i mod 5 で5で割った余り という意味です。

ちなみに表の各セルのテキストは
Cell(行,列).Shape.TextFrame.TextRange.Text
と階層が深いのはパワポVBAの仕様なのであきらめるしかありません。。

以上でした(ΦωΦ)

再利用可能な自分用ライブラリを作るために(自分ルール)

VBAでささっと自分で作った部品を読み込ませて使えると,プログラミングできる人がほとんどいない職場ではなんとなく仕事ができる雰囲気になるので,それを実現してみたい。

まとまらないものは,ブログに書きなぐって載せて置いたら検索でちょっと調整して使える。

成熟したものは,テキストファイルでいつも読み取れるものに入れておけば,再利用できるようになる。

なんとか目指したい。


クラスモジュールはカプセル化すれば外部に無用な影響は及ぼしにくいでしょうから楽ですね。

でも,クラスモジュールは便利で楽しいですが,なんでもかんでもクラスモジュールにするのは仰々しい。


問題は標準モジュールの使いまわしか。

標準モジュールでちゃちゃっとすませたいこととかありますしね。テンプレート的な標準モジュールを部品として用意しておいて,それを直接編集できるように考えるのもいい。



そのあたりを考えると,一番気になるのは変数のかぶり。

プライベート変数とスコープが広い変数がかぶると具合がわるいです。


普段はカウンタの変数もi,j,k,・・・でいいですが,繰り返し使うやつには少し配慮したいものです。

基本的に私はスネーク記法というのを自然には用いないので,逆にテンプレート的なものにはスネーク記法で書いておけば被らなくなるのかな。

パスカル記法 … UserNameのように単語の先頭を大文字にする
キャメル記法 … userNameのように最初の単語だけ先頭小文字で2つ目以降の単語は先頭を大文字にする
スネーク記法 … user_nameのように小文字の単語をアンダーバーで区切る
大文字記法 … USER_NAMEのように大文字の単語をアンダーバーで区切る

t-homさんのVBA コーディングガイドライン より引用

自分ルールでは,

使いまわす標準モジュールの変数はスネーク記法!

というのを守って,標準モジュールはbasファイル,クラスモジュールはclsファイルで保存していつも持ち歩くようにすればなんとなくやれそうですね。

OneDriveが使える環境でなら,そこに貯めておけば便利だな。職場では使えないんだよなぁ。セキュリティ上しかた無いけど残念です。

OneDriveが使えないところではどうするかはまた考えるとして,とりあえずスタートを切って修正していけばいいですね。

そろそろ,スマートにコードの再利用ができる人になりたい。

見つからないからささっと作ってしまえ,というのも楽しくていいんですが,効率も目指さないとですね・・(ΦωΦ)

今年度はこの方向性で,パワーポイントのVBAも書き直したり再調整したりしつつ,ブログも書いていきたい。

教材にはパワーポイントVBA,校務にはエクセルVBA,ワードVBAがとても便利なことが多いので,やっぱ3つともやっていくことになりそうですね。

勇者ヨシヒコの メレブさんの

 「おれは、この呪文に*** と名付けたよ」

というのを想像しながら,モジュールに名前をつけつつライブラリをためていきたいものです。

勇者ヨシヒコまた見たいなぁ( ´ー`)

(ΦωΦ)

やっと,Huluを見ながら仕事ができる余裕が出てきました。

Hulu見ながらでも,自宅で仕事をしている時点でどうかと言われそうですが,

仕事と趣味の境界が私には無いようです。

教材を作ることも純粋に楽しく,それで少しでも授業が改善されればなおのこと。

時間割を作るのは今年はかなり厳しく,これにはストレス半端ありませんでしたが,

ようやく折り合いがつきそうになり,少し余裕が出てきました。

Webシステムで全国の教育情報システムが作られることが多いようですね。

Webへの入力はあまり便利にはなっていませんので,データ取り込みの仕組みがだいたいあることが多いです。

やはりExcelは万能で,そのようなときにとても便利に動いてくれます。

データの入力規則を使えばパソコンが苦手な人にも比較的利用しやすいユーザーインターフェイスを提供できますので極めて便利ですし,

データ入力規則に適合するテキストデータを効率的に用意できれば,直接Webを操作しなくても望みのことを楽にできます。


今回の時間割の場合は

  時間割作成ソフトで作成(ミスの確認のためにも便利です)
    ↓
  CSV形式テキストでExcelに。
    ↓
  Excel上で職場の先生や生徒への連絡の作成 様々な形式を日々作るのでマクロが無いとけっこう面倒(;´▽`A``
    ↓
  このデータをWeb取り込み用に変換

VBAできちんと作れば,ミスの段階を限定できるので,かなり確認の段階を減らせて,だいぶ時間と手間の軽減ができそうです。

これを手作業でしないといけないならほんと,気が滅入ります。。自分用とはいえVBAは役に立ちますね。

複雑なものは組めなくてもいいけど,ある程度VBAが使えるように皆がなればずいぶん働き方が変わるんだろうなぁと思わざるを得ません。


同じ規則で並び替えれば,若干の相違が含まれていても変換テーブルを作るのが比較的容易なので,ソートもミスの減少,手作業の補助として有効です。

今回は取り込みながら並び替えるという方法をコードにしてみながら遊んでいましたが,

前使ってたコレクションのソート機能をインポートすればいいだけの話でした。


組んでみたいという気持ちがあり,楽しみの意味で組むことに問題は無いんですが,どうしてもコードの再利用がうまくできていないことは以前からの悩みです。

家で仕事できるときは,自分のブログを検索して再利用することはできますが,職場ではネットを見れません。

どうやったらいいんでしょうね。今はがっつりコード組むのにはまれていた時の分をもうけっこう忘れていることがよくわかりました。

同じようなコードで重なったとしてもまた頭の中作り直していかないといけないですね。自分の記憶力の無さには敬服します(;´▽`A``ヒドスギル。

コードのエクスポートはできるわけですし,basファイルをうまく管理できる仕組みを作らないといけないかなぁ。

これだけ忘れるのが早いと,記憶,能力を身に着けるより,外部記憶手段を用意しないて管理する手段を準備しないと先に進めない。。

教材の準備のほうに移行できそうな気がしてきたので,Powerpointのコード遊びにも戻れる気がしています。

コード管理どうやったらいけるかなぁ。。(;´▽`A``

あれれ(;´▽`A``

VBAでいろんな作業をしつつ,データ処理ばっかりやっているので,ほんとここには何も書けていないんですが,

以前から不思議なことが1点と,今回うまくいかなくて困っていることが1点。

不思議なことは,Collectionを使っているとき,突然強制終了をすること。

まぁまぁ頻繁にです。

下記のコードでもよく強制終了される。

せめてエラーを吐いて怒るくらいにしてほしいのにな。

でも,Excelを起動しなおすと,普通にコードは動いてしまい,どこかおかしいわけではないようなんです。

頻繁に強制終了されるのは けっこうストレス(; ・`д・´)



うまくいかなかったものは自己解決しました。

ソートを書くのが大変なので,入れなおす時に評価しながら入れて終わらせてしまおうという考え方をしました。

入れ替えを頻繁にしないでいいので,シンプルだし,人の感覚で並び替えるのってこんなかんじだなぁと思いながら作りました。

Sub ソース科目取得()
    Dim dic As Scripting.Dictionary
    Dim i As Long, j As Long, k As Long, l As Long
    Dim SourceSht As Worksheet: Set SourceSht = ThisWorkbook.Worksheets("ソース")
    Dim arr科目 As String, 時間割行番号 As Long
    Dim tmp科目クラス As String
    Dim col As Collection, flg As Boolean
    i = 2
    Do
        時間割行番号 = Me.Cells(i, 1)
        Set dic = New Dictionary
        Set col = New Collection
        arr科目 = ""
        
        For j = 4 To 33
            tmp科目クラス = SourceSht.Cells(時間割行番号, j) & SourceSht.Cells(時間割行番号 + 1, j)
            If tmp科目クラス <> "" And tmp科目クラス <> "※※" Then dic(tmp科目クラス) = 1
        Next
        l = 1
        For j = 0 To dic.Count - 1
            tmp科目クラス = dic.Keys(j)
            flg = False
            If l = 1 Then
                col.Add tmp科目クラス
                flg = True
            Else
                For k = 1 To col.Count
                    If tmp科目クラス < col(k) Then
                        col.Add tmp科目クラス, before:=k
                        flg = True
                        Exit For
                    End If
                Next
            End If
            If flg = False Then col.Add tmp科目クラス
            l = l + 1
        Next
        Stop
        For j = 1 To col.Count
            arr科目 = arr科目 & "■" & col(j)
        Next
        Me.Cells(i, 4) = Mid(arr科目, 2)
        i = i + 1
    Loop Until Me.Cells(i, 1) = ""
End Sub

f:id:chemiphys:20170408024932p:plain

( ´ー`)フゥー...

時間割作成 4日目 やっととりあえず職員の皆さんに配れるものができました。

ほんっとに,今までで一番苦労した気がする 条件多かった(;´▽`A``

所属校に慣れればもう少し短縮できそうなので,未熟なせいではありますね(;´▽`A``

来年また作れる機会があったら,今度は負けないように準備しておこうと思います マケナイ(; ・`д・´)


どの条件を軽く処理して,どの条件を重く受け止めるかを要望の中から判断するのが大変なのと,

転勤したてで慣れていないため,極めて情報の少ない推測で判断しないといけないのがだめですね。

まぁ,スタートをやっときれそうなので ちょっとだらだら書いているところです。

全体はできたものの,いろいろな形式に加工するのはVBAで遊ぶ領域ですので,

まだ,記事を書ける余裕はありませんが,VBAで遊べる段階に来ました。

時は否応無しに過ぎていくので,早いところ,いろいろ片付けて,教材づくりをしたり,ここでVBAのこと書いたりしたいものです(;´Д`)

ちょっと書けてないです(;´▽`A``

本日の地方の新聞に県の人事が公表されました。

なので,もう解禁ですね。

4/1から職場が変わるので,その準備に追われていて,さすがに更新ができていません(;´▽`A``

通勤時間がぐぐっと短縮されますので,ずいぶん体には優しくなります。

まったく知らない学校ですが,時間割づくりがたぶん待っていますので,今年度の時間割をもらってきていて,それを分析中。

普段ならそこまでしなくても間に合わせてきたんですが,

来年度って

4/1(土) 休日返上で仕事
4/2(日) お休み
4/3(月) 作業
4/4(火) 4/1の分お休み
4/5(水) 作業
4/6(木) 始業式

こんな感じです。4/3に始めたら絶対に間に合わないので,振り替えてなお,あきらかに準備期間が短いというスタート。

しかも,転勤してすぐなので,その学校のことは知りません。

でも,1年間を大きく左右する時間割をたぶん作成します。(;´▽`A``

4/3(月)にはある程度形にしないといけない。

4/1(土)の昼までに資料をもらって,1.5日で作る・・・

(´▽`) '`,、'`,、

さすがに,頭の中でシミュレーションをしておかざるを得ません。

まったく情報は無いけれど,推測できる情報を頭で整理して準備するしか。。

そんなの無理だよとあきらめないで済むところは,性格だと思います。デキルサ ヤルサと思ってる。

県内全学校おなじ状況で,各校誰かが苦労しているわけです。

自分だけできないって言ってもねぇ。。

とまぁ,曜日の不具合を呪いながら,もう数日はたぶんまともに更新しないかもしれません。

読者になっているページは楽しみに息抜きに読んでいます(ΦωΦ)

Powerpoint VBA 表のそれぞれのセルの文字に処理を行う

さっきの続きです。

ひさびさにPowerpointのVBAのことが書けるのでとても気分がいいです。

タイトル詐欺になるので!

やっていることはさっきの続きで,たくさんのセルや文字があるので,こういう時こそマクロの出番だよ,というものです。

教材作成と並行していますので,勢いで書いています。スミマセン。

コードはこちら。さくっと使えるようにということで,選んだテーブルに処理を行います。

Sub 書式調整()
    Dim TargetTable As Table: Set TargetTable = ActiveWindow.Selection.ShapeRange.Table
        
    Dim r As Row, c As Cell, tr As TextRange
    For Each r In TargetTable.Rows
        For Each c In r.Cells
            For Each tr In c.Shape.TextFrame.TextRange.Characters
                If tr = Chr(11) Then tr.Delete
                If IsNumeric(tr) = True Then
                    tr.Font.Size = 12
                    tr.Font.Subscript = msoTrue
                Else
                    tr.Font.Size = 14
                End If
                
            Next
        Next
    Next
        
End Sub

For Eachだらけですね(ΦωΦ)好きなんです。

Table → Rows → Cells → Characters → 各Character (オブジェクトとしてはTextRangeオブジェクトになります)
と全てコレクションオブジェクトなので,For eachで降りていけます。RowsはColumnsでもいけるようです。
アクセスする順番は変わりますけど。。

たまたまわたしがやったやつでは, 改行が Chr(11)でしたので,邪魔なので削除しています。

数字は小さくしたかったので IsNumericで判断して,小さくし,さらに下付き(SubScript)にしています。

そうでなかったらSizeを14にする。

あとは数値をトライアンドエラーで自分好みのサイズの組み合わせにしていきます。

f:id:chemiphys:20170327224624p:plain
※テキストが 金属と非金属逆でした ハズカシ(;´▽`A`` 修正

私好みな感じになりました。

こんなのいちいちやっていると大変なので,これはマクロの出番ですね。