壮年エンジニアpothのひとりごと

壮年エンジニアpothが適当に思い付いたことをつぶやきます。最近始めた株とかプログラム(VBAとかC#)とかが多くなるかな

【エクセルVBA】マクロでエクセルのCSV保存と同じようなCSVファイルを出力する方法

CSVファイル出力で少し手こずったので備忘録。
エクセルファイルをCSVファイルとして出力する方法として、
「名前を付けて保存」で「ファイルの種類」の
CSV(コンマ区切り)」を選んで保存する方法と、
マクロでそれぞれのセルをコンマ区切りで出力する方法があると思います。
今回、エクセルの「名前を付けて保存」でCSVで保存したときは問題ないのですが、
マクロで作成したCSVファイルではエラーが出ました。
通常マクロでCSVファイルへ出力するときは以下のようなコードを書くと思います。

Sub CSV出力()
    Dim fileName As Variant
    Dim csvFile As String
    csvFile = ThisWorkbook.Path & "\" & "test.csv"
    Open csvFile For Output As #1
    Dim i As Long, j As Long
    i = 1
    j = 1
    Do While Cells(i, 1).Value <> ""
        Do While Cells(i, j).Value <> ""
            Print #1, Cells(i, j).Value & ",";
            j = j + 1
        Loop
        Print #1, Cells(i, j).Value & vbCr;
        i = i + 1
    Loop
    Close #1
End Sub

ただし、これだとすでにセルの中にカンマが含まれていたり、
ダブルクォーテーションで囲まれているようなデータの場合、
カンマの部分で分割されたり、ダブルクオーテーションが消えたりします。
f:id:daigorochang:20180816211801p:plain
ただし、CSVで保存したときはセル内のカンマはそのままですし、
ダブルクオーテーションもちゃんと表示されます。
何が違うのでしょうか?
まずエクセルのCSVで保存するときの特徴を調べます。
普通のデータをCSV保存すると、以下の通りになります。
f:id:daigorochang:20180816180348p:plain
ただし、CSVファイルで特殊な意味を持つカンマ「,」や
ダブルクォーテーション「”」が含まれるデータを
CSV保存するとエクセルが勝手に解釈して
ダブルクォーテーションを追加したりしてくれます。
f:id:daigorochang:20180816180820p:plain
何が起こったのでしょうか?ひとつずつ見ていきます。
①セルA1
「aaa,aaa」とカンマが含まれていますが、
このカンマはCSVの区切りではないので、
文字列ということを示すためにダブルクォーテーションで囲まれています。
こうすることで、ダブルクオーテーション内のカンマは文字列と判断されて、
区切りのカンマとは区別されます。
②セルB1
「"bbb"」とセル内の値がダブルクォーテーションで囲まれています。
そのままだと消えてしまうので、文字列を表すダブルクォーテーションで囲んで、
ダブルクォーテーションを特殊な記号では無いと表すための
ダブルクォーテーションが追加されています。
詳しくはこちらを参照ください。Office TANAKA - Excel VBA Tips[ダブルコーテーションの表示]
③セルC1、D1
これらも上記と同様の理由です。
なんだかダブルクォーテーションだらけですね。

とりあえず、マクロでエクセルのCSV保存とほぼ同じファイルを作成するには、
①セル内にカンマがあっても大丈夫なように、
 セル単位でダブルクォーテーションで囲う
②ダブルクオーテーションは重ねる必要があるので、
 もともとあるダブルクオーテーションを置き換えて重ねる
 「”」を「””」に置き換えておく
③最後に「””」を「”」に戻す

マクロで書くと以下のような感じです。

    Dim fileName As Variant
    Dim csvFile As String
    Dim myRange As Range
    Dim keyWord1 As String, keyWord2 As String
    Dim bool As Boolean
    Set myRange = ActiveSheet.Cells
    keyWord1 = """"
    keyWord2 = """"""
    bool = myRange.Replace(keyWord1, keyWord2, LookAt:=xlPart)
    
    csvFile = ThisWorkbook.Path & "\" & "test.csv"
    Open csvFile For Output As #1
    Dim i As Long, j As Long
    i = 1
    j = 1
    Do While Cells(i, 1).Value <> ""
        Do While Cells(i, j).Value <> ""
            Print #1, """" & Cells(i, j).Value & """" & ",";
            j = j + 1
        Loop
        Print #1, Cells(i, j).Value & vbCr;
        i = i + 1
    Loop
    Close #1
    bool = myRange.Replace(keyWord2, keyWord1, LookAt:=xlPart)
End Sub

【エクセルVBA】画像に枠線を追加

挿入した画像に枠線を付ける方法

画像を選択した状態で以下のコードを実行でできます。

Sub Border()

  With Selection.ShapeRange.Line
    .Visible = msoTrue
    .ForeColor.RGB = RGB(150, 150, 150)
    .Weight = 3
  End With

End Sub

色は.ForeColor.RGBで指定、上のコードでは(150,150,150)でグレーです。

線の太さは.Weightで指定できます。

以下の図は上のコードで枠線を追加した画像です。

f:id:daigorochang:20180716143417j:plain
枠線追加前後

【エクセルVBA】スケジュール(ガントチャート)作成マクロ2 ~表作成まで~

まずはスケジュールの大枠である表を作成していきます。

【準備】

 セルD2にスケジュールの一番初めの日、セルD3に最終日を入力します。

(タスクの開始、終了日を範囲としたmin関数とmax関数を使ってもいいです。)

 「祝日」シートを作成し、A列に祝日を羅列しておきます。

【マクロ】
まず最初にいくつか定義しておきます。

    Dim startday As Range
    Dim endday As Range
    Dim daysStartCell As Range
    Dim taskCell As Range
    Dim printAreaStart As Range
    Dim xxx As Range
    Dim GetMonth As Long
    Dim GetWeek As Long
    Dim holydayCell As Range

スケジュールの開始日(セルD2)と最終日(セルD3)を変数に取り込みます。そして日付と書き始めるセルをセルI6と指定します。その他もろもろも取り込みます。

    Set taskCell = Range("G6")          'タスクのタイトルセルを指示
    Set startday = Range("D2")         '作成する表の初めの日付を入手
    Set endday = Range("D3")           '作成する表の最後の日付を入手
    Set daysStartCell = Range("I6")    '表作成で日付を書き始めるセル
    Set printAreaStart = Range("G4")    '印刷範囲の初めを指定
    Set holydayCell = Worksheets("祝日").Range("A:A")

セルI6から右へ日付を記入しておきます。すごく単純にForで記述します。

    '日付を埋める
    Dim i As Integer
    For i = 0 To endday.Value - startday.Value
        daysStartCell.Offset(0, i) = startday.Value + i
    Next i

日付の記入が終わると次は、その日付に合った週番と月をその記入します。

For Eachで記入した日付を順番に見ていきます。月はMonth関数で取得し、月が変わるたびに2つ上のセルへ記入します。
週番はformat関数で取得します。一番初めの日と毎週日曜日の1つ上のセルへ記入します。

    For Each xxx In Range(daysStartCell, daysStartCell.End(xlToRight))  'xxxは週番
        '何月か書く
        GetMonth = Month(xxx)                                           '日付から何月か確認
        If GetMonth & "月" <> xxx.Offset(-2, 0).End(xlToLeft) Then      'まだ何月か書いていなければ
        xxx.Offset(-2, 0) = GetMonth & "月"                             '何月か書く
        End If
       '週番号を書く
        GetWeek = Format(xxx, "ww")
        If Weekday(xxx) = 1 Or "W" & GetWeek <> xxx.Offset(-1, 0).End(xlToLeft) Then
            xxx.Offset(-1, 0) = "W" & GetWeek
        End If
    Next

次に罫線を作成します。

まずは、表を作成する範囲を把握します。その範囲全体の罫線を実線で引き、水平な線だけ破線にします。

    '罫線を引く
    Dim LastCol As Integer
    Dim LastRow As Integer
    
    LastCol = Cells(daysStartCell.Row, Columns.Count).End(xlToLeft).Column  '日付が記載されている最後の列
    LastRow = Cells(Rows.Count, taskCell.Column).End(xlUp).Row              'タスクが記載されている最後の行
    Range(taskCell, Cells(LastRow, LastCol)).Select                         'タスクの表題から最後の行列まで選ぶ
    Selection.Borders.LineStyle = xlContinuous                              '全て囲う罫線を引く
    Selection.Borders(xlInsideHorizontal).LineStyle = xlDash                '水平な線は破線にする

f:id:daigorochang:20180313223657j:plain
これだけでも見た目はOKですが、少しこだわります。垂直方向の罫線も週の始まり(土曜と日曜の間)は実線でそれ以外は破線にして、土日祝日はグレーでハイライトするようにします。ここで準備で作成した祝日シートを活用します。作成方法は単純でFor Each関数で記入した日付を見に行って週の始まりなら(日付の上に週番が記入されていれば)何もしない、週の始まりでないなら(日付の上のセルが空欄なら)破線にします。また日付からweekday関数で曜日を確認し土日であるもしくは、祝日シートに記入した日付であればグレーにハイライトします。

    Dim yyy As Range
    For Each yyy In Range(daysStartCell, daysStartCell.End(xlToRight))    'yyyは日付の最初から最後まで選ぶ
        If yyy.Offset(-1, 0) = "" Then                                      'yyyの上が空欄なら
        Range(yyy, yyy.Offset(LastRow - yyy.Row, 0)). _
        Borders(xlEdgeLeft).LineStyle = xlDash                              '垂直な線を破線にする
        End If
        
        '土日に色をつける
        If Weekday(yyy) = 1 Or Weekday(yyy) = 7 Then
            Range(yyy, yyy.Offset(LastRow - yyy.Row, 0)).Select
            With Selection.Interior
              .ThemeColor = xlThemeColorDark2
            End With
        End If
        '祝日に色をつける
        If Not holydayCell.Find(what:=yyy) Is Nothing Then
            Range(yyy, yyy.Offset(LastRow - yyy.Row, 0)).Select
            With Selection.Interior
              .ThemeColor = xlThemeColorDark2
            End With
        End If
    Next

おまけに見出し行の罫線を二重線にし、印刷範囲を指定して終わりです。

    Range(taskCell, daysStartCell.End(xlToRight)).Select
    Selection.Borders(xlEdgeBottom).LineStyle = xlDouble                    '見出し行を二重線にする
    
    ActiveSheet.PageSetup.PrintArea = Range(printAreaStart, Cells(LastRow, LastCol)).Address '印刷範囲指定

f:id:daigorochang:20180313223710j:plain

【エクセルVBA】スケジュール(ガントチャート)作成マクロ

 こんにちは、pothです。
今回はスケジュール作成マクロです。
 業務を進める上でスケジュールは不可欠です。実際作成するとなると、日付を入力したり矢印を挿入したり面倒です。それらを簡単にするマクロです。
 まず、以下のようにタスク名とそのタスクの開始日と終了予定日を入力します。あと▽印を入れたいところにその日付を入力します。
f:id:daigorochang:20180310232648j:plain
 この状態でマクロを走らせると以下のようなスケジュールが完成します。
f:id:daigorochang:20180310231556j:plain
①開始日の一番小さい日付から最終日までの表を作成
②休日を灰色に塗る
③週番とその月を記入しそれぞれのタスクの矢印を引く
④週ごとに実線と破線を引き分ける
ここまでしようと思うと結構大変。それを自動化してくれるマクロです。ついでに、タスクが完了した後は済マークを付けることもできます。
f:id:daigorochang:20180310232232j:plain
 このマクロの作成方法について、今後説明していきます。今日はここまでです。

【株】アルバック株の取引だけで100万近く稼いで最終的には30万近く損したトレード公開

 こんにちは、pothです。
 今回アルバック株のトレードで面白いほど負けたので、反省を込めてこれまでのトレードを振り返ります。特に最後の方は冷静さを失い売れば上がり、買えば下がるという奇跡的な取引をしています。やはり株は冷静な判断が重要ですね。

 まず、アルバック株のトレードを開始したのが、2017年4月ごろです。当時半導体関連が好調で、有機ELも騒がれていました。真空装置はどちらにも必要ですし当時割安(今も?)だったので上がるだろうと思いこの銘柄に決めました。
 4/20、最初はお試し程度に4250円で100株買い、ちょっと上がった5/2に5330円で売却しました。(+5.8万円)
 その後まだ上昇するなーという感じだったので、5/8に5480円で100株買い5/29に6060円で売りました。(+5.7万円、計:+11.5万円)
 調子に乗った私は6/2に6110円で100株買いました。ただしその後株価は下降し始めます。7/4まで下がり続けるのですが、怖いものしらずのpothはナンピン買いを繰り返し400株ほど仕込みました。幸運なことにその後株価は上昇し、7/27に6170円まで戻りその後下がり始めたので8/1に5820円で400株すべて手じまいしました。一応ナンピン買い成功です。(+4.7万円、計:+16.2万円)
 そして、売った直後まだ結構下がったのですぐに5650円で400株購入。その後決算内容も良く決算後8/10に6350円まで急浮上、ただしジリジリ下げ始めたので8/18に5840円で手じまい。 (+7.3万円、計+23.5万円)
 ここまでの取引をチャートに記載するとこんな感じです。この後ももう少しだけ幸運は続きます。
f:id:daigorochang:20180309105956j:plain
 さらに、この持ち合いを抜ければまだまだ上がるんじゃないかと思い、8/18~30で400株ほど平均5925円で仕込みました。すると9/6以降上昇トレンドに入りました。ビビりな私は9/14に200株利確します。今見ると、全然下がる傾向も出てないのでなんでこんなところで売ったんだろうと思います。(+6.9万円、計:+30.4万円)
 その後も株価は上昇し、11/10の好決算から11/13に8930円の高値を付けました。ただし思ったより上がらず11/14に8810円で残り200株売却。9/14に全部売らなくてほんとによかった。(+57.5万円、計:+88.1万円)
 ここからが悲劇の始まりです。
f:id:daigorochang:20180309174929j:plain
 高値で持ち合いを続けていたので私は、「前回同様、上昇するための力を溜めている!ここで仕込んでおかないと後悔する!」と思い11/20~28で300株平均8200円で仕込みました。
f:id:daigorochang:20180309175733j:plain
 そんな簡単にいかないのが株。そこから11月下旬に半導体関連株全体安の影響で暴落。ただpothは「半導体関連と言えど真空装置は有機ELとかいろんなところで使われるから、アルバックは大丈夫だろう」なんてのんきに考えていました。典型的な塩漬け状態。待てども待てども上がる気配なし。そのまま年越し。すると、じわじわ上がってくるではないですか。ここで「やはりpothの目に狂いは無かった」と確信します(完全に間違い)。1/19に8000円を超え8060円まで戻るのですが、仕込んだのが8200円ですので含み損状態。売るタイミングを逃す。またこれぐらいまで持っていると、「次の決算で、好決算が出てぶっ飛ぶんじゃないか」なんていう根拠のない自信が出てきます。結局1/19に8060円の高値を付けて以降、下がり続けているのですが、pothはあろうことか1/31に7360円で100株、2/2に7180円で100株買い増しします。なんせ、2/13の決算でぶっ飛ぶと思ってますから。ただ決算までに大事件発生、パウエルショックだかわからないですが、アメリカ発の同時株安で株価は6800円台に、さすがにまずいと思ったpothは6840円で600株の空売りを入れます。ポジション的には買500売600でさらなる暴落に備えました。すると、予想通り翌日も大暴落なんと6300円台に。。。これはもう止まらないと考え6390円で400株売却し、6360円で200株空売り追加。ここでポジは買100売800。(-53.8万円、計:+34.3万円)
 するとあろうことか、翌日6900円近くまで上がってるじゃないですか!!こうなるともうパニック状態。もともと上がると思っていた株ですから「なぜこの株を信じてやらなかったんだ。やっぱ買いだよね買い!しかももうすぐ決算。今買わないでどうするの!」と空売り入れていた800株を6880円で返済買いし、これからの上昇に向けて6640円で500株購入。(-12.8万円、計:+21.5万円)
 翌日、再暴落。。。でも大丈夫、なぜなら次の日は決算発表日。そして決算日発表アルバック、今期経常を9%上方修正・最高益予想を上乗せ」キターーーーーー!と思って翌日楽しみにしていたのですが、待てども待てども上昇せず。。。。株。。むずい。。。ここまで来ると間違っていたのは自分だと気づく。結局正しいのはその株価ですから。そして3/2~3/6にかけてすべての株を手じまい。(-48.1万円、計:ー26.6万円)
 f:id:daigorochang:20180309184845j:plain
 今回のトレード何が悪かったか、どうトレードすべきだったかを今度の記事で考察したいと思います。

【エクセルVBA】画像をエクセルに貼るマクロ2

こんにちは、pothです。
前回「画像をエクセルに貼るマクロ1」で紹介しいたマクロのコードを以下に貼っておきます。
ドシロウトのコードなので使用する場合は自己責任でお願いします。

準備としてはシートのB1セルに列数、B2に画像高さを書いておけば使えます。

Sub pasteDirImage()
' 変数定義
Dim firstRow As Integer
Dim myFileName As String
Dim targetCol As Integer
Dim targetCell As Range
Dim shell As Object
Dim myPath As Object
Dim pos As Integer
Dim isImage As Boolean
Dim tempPath As String
Dim picHeight As Long
Dim picWidth As Long
    
firstRow = 3  '画像を貼り付け開始行を指定
tempPath = ActiveWorkbook.Path  'このエクセルファイルが保存されている場所を取得
picHeight = Range("B2").Value   '貼り付ける画像の高さを取得
    
' フォルダ選択画面を表示
Set shell = CreateObject("Shell.Application")
Set myPath = shell.BrowseForFolder(&O0, "画像が保存されているフォルダを選んでください", _
                                    &H1 + &H10, tempPath & "\")
Set shell = Nothing
 
' フォルダを選択したら...
myFileName = Dir(myPath.Items.Item.Path + "\")
i = 0
Do While myFileName <> ""
    ' ファイル拡張子の判別
    isImage = True
    pos = InStrRev(myFileName, ".")
    If pos > 0 Then
        Select Case LCase(Mid(myFileName, pos + 1))
            Case "jpeg"
            Case "jpg"
            Case "gif"
            Case "tif"
            Case Else
                isImage = False
            End Select
        Else
            isImage = False
    End If
    ' 拡張子が画像であれば
    If isImage = True Then
        targetCol = 1 + i * picWidth    ' 貼り付ける列指定
        ' 貼り付け先を選択
        Cells(firstRow, targetCol).Select
        ' 貼り付け
        Set targetCell = ActiveCell
        Set myShape = ActiveSheet.Shapes.AddPicture( _
            fileName:=tempPath & "\" & myFileName, _
            LinkToFile:=True, _
            SaveWithDocument:=False, _
            Left:=Selection.Left, _
            Top:=Selection.Top, _
            Width:=0, _
            Height:=0)
        With myShape
            .LockAspectRatio = True
            .ScaleHeight 1, msoTrue
        End With
        ' 画像のサイズを調整
            myShape.Select
            Selection.Height = targetCell.Height * picHeight
        ' 貼り付けた画像の幅取得
        picWidth = Application.WorksheetFunction.RoundUp(Selection.Width / targetCell.Width, 0)
        ' 貼り付けた画像の下にファイル名を記入
        Cells(firstRow, targetCol).Offset(picHeight, 0) = myFileName
        i = i + 1
        ' 指定した列数に達したら、次の行へ行って列を元に戻す
        If i = Range("B1") Then
            firstRow = firstRow + picHeight + 1
            i = 0
        End If
    End If
    myFileName = Dir()
    Loop
    MsgBox "画像の読込みが終了しました"
 End Sub

【エクセルVBA】画像をエクセルに貼るマクロ1

こんにちはpothです。

はじめての記事は、エクセルVBAを使ってエクセルファイルに写真とかの画像をペタペタ貼り付けるマクロの紹介です。

実験とかで結構たくさん写真を撮ることがあるのですが、それをエクセルで編集したいと思ったら結構な手間なんです。

例えば、条件が3つあって2枚ずつ写真を撮ったとします。

f:id:daigorochang:20180225172913j:plain

これをエクセルに貼り付けようとすると、 

f:id:daigorochang:20180225172935j:plain

こんな感じになります。

ここから、「サイズ変更」⇒「きれいに並べる」⇒「写真の説明」ってしていくとそれだけで結構大変です。

今回写真が6枚しいかないですが、それが20枚とか、100枚とかになるともうパニックです。並べてるうちに「どの写真がどの条件だっけ?」とかなります。

これを楽にするマクロです。完成形はこんな感じ

f:id:daigorochang:20180303120512j:plain

エクセルのセル何行分のサイズにするか指定し、画像を貼り付ける列を指定します。その2つのパラメータを入力して、ボタンを「ポチっ」

すると、フォルダーの選択画面になるので貼りたい画像が保存されているフォルダーを選択すると、全部自動で貼り付けてくれます。またファイル名も下に書くようにしています。

上の画像は2列で8セル分のサイズにしてます。3列で3セル分にするとこんな感じ

f:id:daigorochang:20180303121353j:plain

ただ画像をそのまま貼り付けるので、写真などの重いデータを大量に貼るとエクセルが非常に重くなるので、あらかじめフリーソフトでデータを軽くしておきます。おすすめは「縮小専用」

forest.watch.impress.co.jp

具体的なコードはぼちぼち書いていきます。