[質問]先頭の1行をファイル名にして保存

  1. mery大変愛用しています。味のあるブログもかなりツボです。

    件名の通りのマクロを作りたいのです。
    http://d.hatena.ne.jp/Fio/20090620/p1
    を参考にしたのですが、苦戦中です。
    希望としては「日付-先頭行.txt」の形式で保存したいです。
    どなたかお願いできないでしょうか。

     |  asakura  |  返信
  2. なんかそれっぽいものができたので。
    あんまりテストしてないですがとりあえず動くっぽいです。

    /*
        日付取得周り参考:http://blog.livedoor.jp/takaaki_bb/archives/50387503.html
    */
    with (document.selection) {
        var selword;
        var date = getYYYYMMDD()
        StartOfDocument();
        SelectLine();
        selword = Text;
        selword = filenameescape(selword);
    }
    Document.Save("C:\\"+getYYYYMMDD()+"_"+selword+".txt");//C:\直下

    /*
        日付関連
    */
    function getYYYYMMDD() {
        var today = new Date();
        return (today.getYear() + format2d(today.getMonth() + 1) + format2d(today.getDate()));
    }

    function format2d(intValue) {
        if (intValue < 10) {
            return ("0" + intValue);
        } else {
            return (""  + intValue);
        }
    }

    /*
        禁止文字変換
    */
    function filenameescape(filename){
        var re;
        re = /:/g;
        filename = filename.replace(re, ":");
        re = /;/g;
        filename = filename.replace(re, ";");
        re = /\//g;
        filename = filename.replace(re, "/");
        re = /\\/g;
        filename = filename.replace(re, "¥");
        re = /\|/g;
        filename = filename.replace(re, "|");
        re = /,/g;
        filename = filename.replace(re, ",");
        re = /\*/g;
        filename = filename.replace(re, "*");
        re = /\?/g;
        filename = filename.replace(re, "?");
        re = /"/g;
        filename = filename.replace(re, "”");
        re = /</g;
        filename = filename.replace(re, "<");
        re = />/g;
        filename = filename.replace(re, ">");
        return filename;
    }

     |  miso  |  返信
  3. > 希望としては「日付-先頭行.txt」の形式で保存したいです。

    それだけだと、作っても自分では使わないだろうと思いまして、
    少し工夫してみたものを作ってみました。

    その代り改変して機能を変えても、結構です。

    > なんかそれっぽいものができたので。
    とすでに、miso氏が書かれていましたが、参考にさせて頂き
    自分でもつくってみました。

    スクリプトは、下記です。

    /* [参考にしたスクリプト]
    http://d.hatena.ne.jp/Fio/20090620/p1

    http://blog.livedoor.jp/takaaki_bb/archives/50387503.html

    http://www.haijin-boys.com/weblog/
    のmiso氏の2011年10月14日 00時10分の投稿記事
    */

    /*
    先頭の1行をファイル名にして保存.js
    [1行目の指定例]
    test
      test
    test.txt
    ' test.vbs
    // test.js
    # test.rb
    # test.  rb
    などを想定しました。
    ※フルパス指定は、不可です。(ファイル名のみ指定してください。)
    */

    var wsh_shell = new ActiveXObject("WScript.Shell");
    var fso = new ActiveXObject("Scripting.FileSystemObject");

    // マイドキュメントフォルダを指定
    // 日付+先頭の1行目で保存。
    var my_dir1 = wsh_shell.SpecialFolders("MyDocuments");
    var dir1_txt = "マイドキュメントに保存";

    // [設定箇所] ////////////////////////////////////
    // 好みのフォルダを指定
    // 先頭の1行目で保存。(日付は付加しません)
    // ( これは、一例です。 変更する必要があります。 )
    var my_dir2 = "C:\\Tool\\Mery\\My Macros";
    var dir2_txt = "Meryマクロフォルダに保存";
    // ///////////////////////////////////////////////

    if (document.Name) {
      Alert("無題ではありません。");
      Quit();
    }

    var date = getYYYYMMDD();
    var selection = document.selection;
    selection.StartOfDocument();
    selection.SelectLine();
    var word = selection.Text;
    word = filenameescape(word);
    // .txtとファイル名が出来ないように対処する。
    // .txt.txtというファイル名なら可能。
    if (fso.GetBaseName(word).length === 0) {
      Alert("ファイル名が、ありません。");
      selection.StartOfLine(false, mePosLogical);
      Quit();
    }

    var pop = CreatePopupMenu();
    // 「my_dir1フォルダ」に日付+先頭の1行目で保存。
    // 拡張子が指定されていない場合には、「.txt」とする。
    pop.Add(dir1_txt, 1);
    // 「my_dir2フォルダ」に先頭の1行目で保存。(日付は付加しません)
    // 拡張子が指定されていない場合には、「.txt」とする。
    pop.Add(dir2_txt, 2);
    var popnum = pop.Track(mePosMouse);
    switch (popnum) {
      case 1:
        var file_name = getYYYYMMDD() + "-" + word;
        file_save(my_dir1);
        break;
      case 2:
        var file_name = word;
        file_save(my_dir2);
        break;
      default :
        Alert("キャンセルしました。");
    }
    selection.StartOfLine(false, mePosLogical);

    function file_save(dir) {
      if (fso.GetExtensionName(file_name).length === 0) {
        file_name += ".txt";
      }
      // ファイル名が長すぎないように調整。
      // ( 全角文字のみの場合特に注意 )
      if (fso.GetBaseName(file_name).length > 50) {
        file_name = fso.GetBaseName(file_name).slice(0, 50) +
          "." + fso.GetExtensionName(file_name);
      }
      var path = fso.BuildPath(dir, file_name);
      if (fso.FileExists(path)) {
        Alert("同名ファイルが存在します。");
      } else {
        document.Save(path); document.Save();
      }
    }

    // 日付関連
    function getYYYYMMDD() {
      var today = new Date();
      return (today.getYear() + "-" + format2d(today.getMonth() + 1) + "-" + format2d(today.getDate()));
    }

    function format2d(intValue) {
      if (intValue < 10) {
        return ("0" + intValue);
      } else {
        return (""  + intValue);
      }
    }

    // 禁止文字変換
    // (ファイル名として使えない文字, スクリプトのコメント, 空白文字)
    function filenameescape(filename) {
      var re = [];
      re[0]  = /:/g; re[1]  = /;/g;  re[2]  = /\//g; re[3]  = /\\/g; re[4]  = /\|/g;
      re[5]  = /,/g; re[6]  = /\*/g; re[7]  = /\?/g; re[8]  = /"/g;  re[9]  = /</g;
      re[10] = />/g; re[11] = /'/g;  re[12] = /#/g;  re[13] = /\s/g;
      for (i = 0; i <re.length; i++) {
        filename = filename.replace(re[i], "");
      }
      return filename;
    }

     |  いっち  |  返信
  4. いっちさん ありがとうございます。

    いやーこれも幅広く使えるやつです。
    色々と応用がききそうですし、細かくその行が何を行なっているのかが記載されているので、
    自分でもいくつか追加したり、削ったりしながら勉強してみたいと思います。
    同じ事を指していても、お2人の書き方が少しづつ違っているのが面白かったです。

    ところで、質問です。

    「日付関連」についてです。
    私は、「2011.10.14-ファイル名.txt」 で保存するので、以下に変更してみると、

      return (today.getYear() + ". + format2d(today.getMonth() + 1) + "." + format2d(today.getDate()));

    拡張子がなく、保存されてしまいます。

    2つ目の"."が拡張子と混同されて消されるのだろうかと想像は出来るのですが。。。

    ぜひとも使ってみたいので、よろしくお願いします。

     |  asakura  |  返信
  5. > ところで、質問です。

    > 「日付関連」についてです。
    > 私は、「2011.10.14-ファイル名.txt」 で保存するので、以下に変更してみると、

    >   return (today.getYear() + ". + format2d(today.getMonth() + 1) + "." + format2d(today.getDate()));

    > 拡張子がなく、保存されてしまいます。

    > 2つ目の"."が拡張子と混同されて消されるのだろうかと想像は出来るのですが。。。

    下記のfunctionを、差替えてください。

    function file_save(dir) {
      if (fso.GetExtensionName(file_name).length === 0) {
        file_name += ".txt";
      }
      for (i = 0; i < 2; i++) {
        file_name = file_name.replace("-", ".");
      }
    // ファイル名が長すぎないように調整。
    // ( 全角文字のみの場合特に注意 )
      if (fso.GetBaseName(file_name).length > 50) {
        file_name = fso.GetBaseName(file_name).slice(0, 50) +
          "." + fso.GetExtensionName(file_name);
      }
      var path = fso.BuildPath(dir, file_name);
      if (fso.FileExists(path)) {
        Alert("同名ファイルが存在します。");
      } else {
        document.Save(path); document.Save();
      }
    }

    ===================================================================
    下記は、変更しないでください。
    // 日付関連
    function getYYYYMMDD() {
      var today = new Date();
      return (today.getYear() + "-" + format2d(today.getMonth() + 1) + "-" + format2d(today.getDate()));
    }
    ===================================================================
    ファイルの1行目には、拡張子の為の"."以外は、入れないようにしてください。
    ただし、abcd.efgh.txt
    などと、予め拡張子まで書いている場合には、問題ありません。

     |  いっち  |  返信
  6. 申し訳ありません。
    もう一度訂正します。

    function file_save(dir) {
      if (fso.GetExtensionName(file_name).length === 0) {
        file_name += ".txt";
      }
      if (flg) {
        for (i = 0; i < 2; i++) {
          file_name = file_name.replace("-", ".");
        }
      }
    // ファイル名が長すぎないように調整。
    // ( 全角文字のみの場合特に注意 )
      if (fso.GetBaseName(file_name).length > 50) {
        file_name = fso.GetBaseName(file_name).slice(0, 50) +
          "." + fso.GetExtensionName(file_name);
      }
      var path = fso.BuildPath(dir, file_name);
      if (fso.FileExists(path)) {
        Alert("同名ファイルが存在します。");
      } else {
        document.Save(path); document.Save();
      }
    }

    さらに下記も訂正します。

    var pop = CreatePopupMenu();
    // 「my_dir1フォルダ」に日付+先頭の1行目で保存。
    // 拡張子が指定されていない場合には、「.txt」とする。
    pop.Add(dir1_txt, 1);
    // 「my_dir2フォルダ」に先頭の1行目で保存。(日付は付加しません)
    // 拡張子が指定されていない場合には、「.txt」とする。
    pop.Add(dir2_txt, 2);
    var popnum = pop.Track(mePosMouse);
    var flg = false;
    switch (popnum) {
      case 1:
        var file_name = getYYYYMMDD() + "-" + word;
        flg = true;
        file_save(my_dir1);
        break;
      case 2:
        var file_name = word;
        file_save(my_dir2);
        break;
      default :
        Alert("キャンセルしました。");
    }
    selection.StartOfLine(false, mePosLogical);

     |  いっち  |  返信
  7. いっちさん、ありがとうございます

    なるほど、全ての問題の元はやはり、「.」が拡張子以外に含まれていることですね。

      if (flg) {
        for (i = 0; i < 2; i++) {
          file_name = file_name.replace("-", ".");
        }

    ファイル名に0以上含まれる「-」と「.」を、replaceでファイル名に戻してあげているという訳なんですね。面白い!

    色々試した結果、個人的な記述のルールが、
    「1行目に題名」「3行目の日付」(必ずしも今日の日付ばかりとは限らないので)です。
    そこで、題名=word、日付=dateとし 以下のように

    var selection = document.selection;
    selection.StartOfDocument();
    selection.SelectLine();
    var word = selection.Text;
    word = filenameescape(word);

    var selection = document.selection;
    selection.StartOfDocument();
    selection.LineDown(false, 1);
    selection.LineDown(false, 1);
    selection.SelectLine();
    var date = selection.Text;
    date = filenameescape(date);

    とします。

    var popnum = pop.Track(mePosMouse);
    var flg = false;
    switch (popnum) {
      case 1:
        var file_name = date + "-" + word;

    に書き換えてみました。すると、replaceして返すという作業は同じはずなのに、拡張子が消えて保存されます。

    試しに、3行目の日付を、2011_10_17とすると拡張子付きで保存されます。

    うーん、難しいけど面白い。ぜひ、よろしくお願いします。

     |  asakura  |  返信
  8. こんばんは。

    > 色々試した結果、個人的な記述のルールが、
    > 「1行目に題名」「3行目の日付」(必ずしも今日の日付ばかりとは限らないので)です。

    でしたら、考え方を根本的に改めて、下記のようなものではいかがでしょうか。
    シンプルな方が、記述のルールを気にしなくて良くて、良いかもしれないです。

    // 1. 始めにテキストに書かれた日付を普通に範囲選択して、Meryでコピーします。
    // 2. 次に題名とする文字列を範囲選択します。
    // 3. その状態から、マクロを実行します。
    //    マクロの内容を一例として、下記に示します。

    // ファイル名は、解り易ければ良いと思いますが、たとえば、「日付-ファイル名.js」とかご自由に。
    var date = ClipboardData.GetData().replace(/[\r\n]/g, "");
    if (date.length === 0) {
          // 日付データとして正しい文字列かどうか、判定させた方が本当は良いような
          // 気もしますが、それは、少し時間をかけてお作りになられてはいかがでしょうか。
      Alert("クリップボードにテキストがありません。");
      Quit();
    }
    var separator = "-";                                    // 日付とファイル名の区切り
    var word = document.selection.Text.replace(/[\r\n]/g, "");
    if (word.length === 0) {
      Alert("文字列を範囲選択してください。");
      Quit();
    }
    document.selection.Collapse(meCollapseStart);           // 選択範囲を解除します。
    var extension = ".txt";                                 // 拡張子
    var file_name = date + separator + word + extension;    // ファイル名

    // 4. 上記の file_name にファイル名としては、使えない文字が含まれていないかチェックします。
    file_name = filenameescape(file_name);

    // 5. そして、クリップボードにファイル名をコピーします。
    ClipboardData.SetData(file_name);

    // 6. 後は、普通にファイルを保存する時に、ファイル名のところに
    //    右クリックで、クリップボードにあるファイル名を貼り付ければ良いと思います。

    // 禁止文字変換   // (miso氏投稿内容 2011年10月14日 00時10分 より)
    function filenameescape(filename){
    var re;
    re = /:/g;
    filename = filename.replace(re, ":");
    re = /;/g;
    filename = filename.replace(re, ";");
    re = /\//g;
    filename = filename.replace(re, "/");
    re = /\\/g;
    filename = filename.replace(re, "¥");
    re = /\|/g;
    filename = filename.replace(re, "|");
    re = /,/g;
    filename = filename.replace(re, ",");
    re = /\*/g;
    filename = filename.replace(re, "*");
    re = /\?/g;
    filename = filename.replace(re, "?");
    re = /"/g;
    filename = filename.replace(re, "”");
    re = /</g;
    filename = filename.replace(re, "<");
    re = />/g;
    filename = filename.replace(re, ">");
    return filename;
    }

     |  いっち  |  返信
  9. いっちさん おはようございます。

    ワクワクして少し早めに始動して、試してみました。

    確かに新Verは分かりやすいですね。全てマクロではなく人力との融合も使いまわせそうです。

    でも、どーしても最初のダイアログが出てきたりした、感動が忘れられなくて、今朝試してみました。

    結果。希望通りになりました!! たぶんですが。。。

    新Verで少し頭が柔らかくなった所で、拡張子が問題なら、判定させずにプラスしてしまえという素人的な発想で、
    「日付 +  題名 + .(ピリオド)」にして

        var file_name = date + "-" + word + ".";

    拡張子を付加する記述から、「.(ピリオド)」を抜いてみました。

    function file_save(dir) {
      if (fso.GetExtensionName(file_name).length === 0) {
        file_name += "txt";
      }

    これで、拡張子まできっちりと出来ました。試したのはまだ3回ぐらいですが。どうでしょう?
    この感じは、子供の頃にプラモデルを完成した時に似てるなぁ。ニヤニヤしてしまう。

     |  asakura  |  返信
  10. asakuraさん、こんにちは。

    > 結果。希望通りになりました!! たぶんですが。。。
    良かったですね。

    >「日付 +  題名 + .(ピリオド)」にして
    > var file_name = date + "-" + word + ".";
    > 拡張子を付加する記述から、「.(ピリオド)」を抜いてみました。

    > これで、拡張子まできっちりと出来ました。試したのはまだ3回ぐらいですが。どうでしょう?

    asakuraさんの方法は、
    1.ファイル名に"."が含まれていても、含まれていなくとも良い。
    2.テキストに、予め拡張子は入れておかない。
      (入れていても、"."を追加すれば、拡張子では無くなる。)

    という方法だと思います。
    asakuraさんのご利用のされかたから考えて、良い方法だと感じました。
    ===================================================================

    個人的には、予め拡張子を指定して、かつ、ファイル名に"."が
    含まれていても、含まれていなくとも良いというものが
    制限付きではあっても、(もしかしたら)良いかもしれないと思いまして、

    下記のようにしてみました。

    下記、functionを追加しました。

    // 拡張子をチェック
    function extension_name_check(filename) {
      // 必要に応じて拡張子を追加する。
      switch (true) {
        case (/\.txt$/i.test(filename)) :
        case (/\.js$/i.test(filename)) :
        case (/\.vbs$/i.test(filename)) :
        case (/\.rb$/i.test(filename)) :
        case (/\.uws$/i.test(filename)) :
          return false;
        default:
          return true;
      }
    }

    下記、functionを修正しました。

    function file_save(dir) {
      // if (fso.GetExtensionName(file_name).length === 0) {
      if (extension_name_check(file_name)) {
        file_name += ".txt";
      }
      if (flg) {
        for (i = 0; i < 2; i++) {
          file_name = file_name.replace("-", ".");
        }
      }
    // ファイル名が長すぎないように調整。
    // ( 全角文字のみの場合特に注意 )
      if (fso.GetBaseName(file_name).length > 50) {
        file_name = fso.GetBaseName(file_name).slice(0, 50) +
          "." + fso.GetExtensionName(file_name);
      }
      var path = fso.BuildPath(dir, file_name);
      if (fso.FileExists(path)) {
        Alert("同名ファイルが存在します。");
      } else {
        document.Save(path); document.Save();
      }
    }

    ===================================================================あと、2011年10月18日 02時34分の自分の投稿内容についてですが、
    下記の2箇所を、訂正させて頂きます。(今朝、気が付きました。)

    // ファイル名は、解り易ければ良いと思いますが、たとえば、「日付-ファイル名.js」とかご自由に。
    // var date = ClipboardData.GetData().replace(/[\r\n]/g, "");
    var date = ClipboardData.GetData().replace(/[\r\n\t]/g, "");    // \t タブを追加 ← ここを訂正しました。
    if (date.length === 0) {
          // 日付データとして正しい文字列かどうか、判定させた方が本当は良いような
          // 気もしますが、それは、少し時間をかけてお作りになられてはいかがでしょうか。
      Alert("クリップボードにテキストがありません。");
      Quit();
    }
    var separator = "-";                                    // 日付とファイル名の区切り
    // var word = document.selection.Text.replace(/[\r\n]/g, "");
    var word = document.selection.Text.replace(/[\r\n\t]/g, "");    // \t タブを追加 ← ここを訂正しました。
    if (word.length === 0) {
      Alert("文字列を範囲選択してください。");
      Quit();
    }

     |  いっち  |  返信
  11. 少し間が空いてしまいましたが、その間、毎日使いたおして不具合がないか確認してみました。
    たぶん、効率は3倍ぐらい上がってますよ。保存先を3つに増やし、ローカル、共有などに分けて、それぞれの下にセパレーターを入れてみたりして、少し出来た気分になってます。

    使用感ですが、私の用途では、全く問題なかったですが、きっと、プログラミング用途では「.(ピリオド)」が入るから、私が今使用しているものでは使えない人も出てきますね。

    まだ、最新版を試してはいませんが、最後に頂いたものを元に又、使いたおしてみます。
    やり始めると、時間が経つのが早いんですよね。。。。

    いっちさん、教えていただいて勉強になってます。ありがとうございます。

     |  asakura  |  返信
  12. asakuraさん、このレス見てくれると良いのですが、

    > 教えていただいて勉強になってます。

    と、書いて頂きまして、恐縮です。
    自分用に、コードを調整している中で、下記を修正しましたので、
    参考までと思いまして、下記を提示させて頂きます。

    自分が投稿(2011年10月14日 21時46分)した

    > // 禁止文字変換
    > // (ファイル名として使えない文字, スクリプトのコメント, 空白文字)
    > function filenameescape(filename) {
    >   var re = [];
    >   re[0]  = /:/g; re[1]  = /;/g;  re[2]  = /\//g; re[3]  = /\\/g; re[4]  = /\|/g;
    >   re[5]  = /,/g; re[6]  = /\*/g; re[7]  = /\?/g; re[8]  = /"/g;  re[9]  = /</g;
    >   re[10] = />/g; re[11] = /'/g;  re[12] = /#/g;  re[13] = /\s/g;
    >   for (i = 0; i <re.length; i++) {
    >     filename = filename.replace(re[i], "");
    >   }
    >   return filename;
    > }

    は、正規表現の見やすさ(解り易さ)を、(もし)考慮したとしても、

    // 禁止文字変換
    // (ファイル名として使えない文字, スクリプトのコメント, 空白文字)

    function filenameescape(filename) {
      var re = [];
      re[0] = /[:;,"<>'#/|*?]/g;
      re[1] = /[\\\s]/g;
      for (var i = 0; i <re.length; i++) {
        filename = filename.replace(re[i], "");
      }
      return filename;
    }

    位で、良いように思います。

    ※このあたりのことは、「詳説 正規表現 第3版 (オライリージャパン)」
    の 8ページ目以降で(これでもか、というほど)くわしく書かれているようです。

     |  いっち  |  返信
  13. ありがとうございます!!
    ただただ、すごいです。たぶん2倍は効率が上がります。
    せっかく、ここまで動くのだからワガママを言わせてください!!
    ―――――――――――――――――――――――――――――――
    「ありがとうございます」という1行目のファイルで説明しますね。

    保存をすると、ファイルは「2011.10.14-ありがとうございます.txt」と作成されます。

    Mery上のタブの名前は「無題*」のまま。

    タブを移動したりなどすると、「2011.10.14-ありがとうございます.txt*」となり、

    閉じようとすると、「2011.10.14-ありがとうございます.txtへの変更を保存しますか?」と、
    ダイアログが出ます。
    ―――――――――――――――――――――――――――――――
    これを、スムーズにすることは難しいことなのでしょうか?

    よろしくお願いします。

     |  asakura  |  返信
スポンサーリンク