カテゴリー
NodeJS

windows の npm 更新で EINVAL (invalid argument) エラーが発生したときの対処方法

npm でモジュールをインストールしていると以下のエラーに遭遇しました。


C:\WINDOWS\system32>npm install -g npm
npm ERR! code EINVAL
npm ERR! EINVAL: invalid argument, read
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\xx\AppData\Roaming\npm-cache\_logs\2019-04-15T19_33_00_354Z-debug.log

これは既知のバグだそうです。以下の手順で更新ができます。

1. PowerShell のセキュリティポリシーを更新


PS C:\WINDOWS\system32> Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force

2. npm-windows-upgrade という モジュールをインストールする。


PS C:\WINDOWS\system32> npm install --global --production npm-windows-upgrade

3. npm-windows-upgrade を実行して、npm を更新


PS C:\WINDOWS\system32> npm-windows-upgrade
npm-windows-upgrade v6.0.1
? Which version do you want to install? (Use arrow keys)
> 6.9.1-next.0
  6.9.0
  6.9.0-next.0
  6.8.0
  6.8.0-next.2
  6.8.0-next.1
  6.8.0-next.0
(Move up and down to reveal more choices)

バージョンを選択できますので、6.9.0 を選びました。

4. しかしインストールされたバージョンは 6.8.0

このブログを書いた時点の最新は6.9.0でしたので、6.9.0 を選択しましたが、インストールされたのは 6.8.0 でした。6.9.0 にアップデートするには、アンインストールしてインストールするしか無いようです。

You wanted to install npm 6.9.0, but the installed version is 6.8.0.

A common reason is an attempted “npm install npm” or “npm upgrade npm”. As of today, the only solution is to completely uninstall and then reinstall Node.js. For a small tutorial, please see https://github.com/felixrieseberg/npm-windows-upgrade#usage.

Please consider reporting your trouble to https://aka.ms/npm-issues.

具体的な方法は以下のページに記載されています。

https://github.com/felixrieseberg/npm-windows-upgrade#issues–support

自分の node バージョンもまだ v10.15.1 なので、インストールしなおそうかな。

5. 参考URL

https://npm.community/t/einval-invalid-argument-read/574/3

https://github.com/felixrieseberg/npm-windows-upgrade#upgrade-npm-on-windows

カテゴリー
NodeJS TypeScript

TypeScript で xlsx ファイルを新規作成する

Excel ファイル (.xlsx)を自動的に出力して欲しいという要望があり、今までExcelVBAで作成していましたが、なんとか開発効率を上げられないかと考えている中で試行錯誤で使ってみましたので、紹介します。

※タイトルに TypeScript で、と書いてますが、あまりTypeScript的な要素は無いです。

1. Nodeモジュール

xlsx というモジュールを使ってみました。インストールは以下のコマンドで行います。


npm i xlsx

2. 配列からワークシートを作成し、Excelファイルを出力する。

import * as xlsx from "xlsx"
const Workbook = xlsx.utils.book_new();
let wsData = [
    ["ヘッダ1", "ヘッダ2"],
    ["値1", "値2"]
]
let ws = xlsx.utils.aoa_to_sheet(wsData)
xlsx.utils.book_append_sheet(Workbook, ws, "AOASheet")
xlsx.writeFile(Workbook, "aoa.xlsx")

実行すると、aoa.xlsxというファイルがカレントディレクトリに出力されます。

以下のようなExcelファイルが作成されるはずです。

  • xlsx.utils.book_new() で、Excelブックを新規作成しています。
  • xlsx.utils.aoa_to_sheet で、配列データを受け取ってワークシートオブジェクトを生成します。その後、
  • xlsx.utils.book_append_sheet で、ワークシートをブックに追加します。このときのワークシート名は AOASheet としています。
  • xlsx.writeFile でファイルに書きだしています。このときのファイル名は aoa.xlsx としています。

3. JSON からワークシートを作成し、Excelファイルを出力する。

import * as xlsx from "xlsx"
const Workbook = xlsx.utils.book_new();
let wsData = [
    { "ヘッダ1":1, "ヘッダ2":2},
    { "ヘッダ1":"A", "ヘッダ2":"B"}
  ]
let option = {
    header:["ヘッダ1","ヘッダ2"]
}
let ws = xlsx.utils.json_to_sheet(wsData, option)
xlsx.utils.book_append_sheet(Workbook, ws, "test1")
xlsx.writeFile(Workbook, "json.xlsx")

実行すると、json.xlsxというファイルがカレントディレクトリに出力されます。

以下のようなExcelファイルが作成されるはずです。

変化点としては、ワークシートとヘッダを分けて定義しています。

  • wsData オブジェクトでデータを定義しています。オブジェクトのメンバーは後述する option のヘッダ項目名と対応します。
  • option オブジェクトで、オプションを定義しています。この中の header 配列でヘッダ名を定義しています。

4. 感想

  1. データベースからSQLで情報をとってきて、Excelに変換する処理だったら、VBAより効率よく実装できそう。
  2. 罫線とかグラフとかの作成方法は分からないので、今後調査する。
  3. このモジュールがMicrosoft製ではないので、出来ないことがあることを念頭に使用する。
  4. すべてを網羅しようと思うと、PowerShellとかC#とかVBAを使用するべき。

カテゴリー
NodeJS

[nodeJS]PDFKitで帳票を作成する方法

QRコードつきのPDF帳票を出力するニーズがあったので、NodeJS のPDFKitを使って出力する方法を紹介します。

1.インストール方法

npm i pdfkit でインストールできます。

NPM:https://www.npmjs.com/package/pdfkit

公式ページ:http://pdfkit.org/

2.オブジェクトの生成とファイナライズ


    let fs = require('fs');
    const PDFDocument = require('pdfkit');
    // PDFDocument オブジェクト生成
    const doc = new PDFDocument;
    // PDF出力先をカレントフォルダの doc1.pdf に設定
    doc.pipe(fs.createWriteStream('doc1.pdf'));
    // x=10、y=10 の位置に文字列「doc1」を印字
    doc.text('doc1',10,10);
    // ファイナライズ・PDF出力
    doc.end();

出力結果は、doc1.pdfのようになります。

2.文字を印字する


    let fs = require('fs');
    const PDFDocument = require('pdfkit');
    // PDFDocument オブジェクト生成
    const doc = new PDFDocument;
    // PDF出力先をカレントフォルダの doc2.pdf に設定
    doc.pipe(fs.createWriteStream('doc2.pdf'));
    // x=10、y=10 の位置に文字列「doc2」を印字
    doc.font('Ronde-B_square.otf')
        .fontSize(10)
       .text('フォントサイズ10の文字',10,10)
       .fontSize(20)
       .text('フォントサイズ20の文字',10,50)
       .fontSize(30)
       .text('フォントサイズ30の文字',10,90)
       .fontSize(40)
       .text('フォントサイズ40の文字',10,130);
    // ファイナライズ・PDF出力
    doc.end();
  • font関数で、フォントファイルを指定します。

フォントは ロンドB https://moji-waku.com/ronde/を使用させていただきました。。

  • fontSize 関数でフォントの大きさを指定します。

出力結果は、doc2.pdfのようになります。

3.罫線を引く


    let fs = require('fs');
    const PDFDocument = require('pdfkit');
    // PDFDocument オブジェクト生成
    const doc = new PDFDocument;
    // PDF出力先をカレントフォルダの doc3.pdf に設定
    doc.pipe(fs.createWriteStream('doc3.pdf'));
    // x=10、y=10 の位置に文字列「doc1」を印字
    doc.text('doc3',10,10);
    //x=100, y=100に移動
    doc.moveTo(100,100)
    //x=100, y=100 から x=100, y=200に線を引く
        .lineTo(100,200)
    //x=100, y=200 から x=200, y=200に線を引く
        .lineTo(200,200)
    //x=200, y=200 から x=200, y=100に線を引く
        .lineTo(200,100)
    //x=200, y=100 から x=100, y=100に線を引く
        .lineTo(100,100)
       .stroke();
    // ファイナライズ・PDF出力
    doc.end();
  • moveTo関数 で座標移動を行います。

  • lineTo関数で線を引きます。

出力結果は、doc3.pdfのようになります。

4.画像を表示する


    let fs = require('fs');
    const PDFDocument = require('pdfkit');
    // PDFDocument オブジェクト生成
    const doc = new PDFDocument;
    // PDF出力先をカレントフォルダの doc4.pdf に設定
    doc.pipe(fs.createWriteStream('doc4.pdf'));
    // x=10、y=10 の位置に文字列「doc4」を印字
    doc.text('doc4',10,10);
    doc.image('./icon.jpg', 100, 100, {
        width: 100
    });
    // ファイナライズ・PDF出力
    doc.end();

出力結果は、doc4.pdfのようになります。

  • image関数で画像ファイル、座標位置、幅などのオプションを指定します。

5.次ページを出力する


    let fs = require('fs');
    const PDFDocument = require('pdfkit');
    // PDFDocument オブジェクト生成
    const doc = new PDFDocument;
    // PDF出力先をカレントフォルダの doc5.pdf に設定
    doc.pipe(fs.createWriteStream('doc5.pdf'));
    // x=10、y=10 の位置に文字列「doc1」を印字
    doc.text('doc1',10,10);
    // ページ追加
    doc.addPage();
    doc.text('doc2',10,10);
    doc.font('Ronde-B_square.otf')
        .fontSize(10)
       .text('フォントサイズ10の文字',10,10)
       .fontSize(20)
       .text('フォントサイズ20の文字',10,50)
       .fontSize(30)
       .text('フォントサイズ30の文字',10,90)
       .fontSize(40)
       .text('フォントサイズ40の文字',10,130);
    // ページ追加
    doc.addPage();
    // x=10、y=10 の位置に文字列「doc3」を印字
    doc.text('doc3',10,10);
    //x=100, y=100に移動
    doc.moveTo(100,100)
    //x=100, y=100 から x=100, y=200に線を引く
        .lineTo(100,200)
    //x=100, y=200 から x=200, y=200に線を引く
        .lineTo(200,200)
    //x=200, y=200 から x=200, y=100に線を引く
        .lineTo(200,100)
    //x=200, y=100 から x=100, y=100に線を引く
        .lineTo(100,100)
       .stroke();
    // ファイナライズ・PDF出力
    doc.end();

出力結果は、doc5.pdfのようになります。

  • addPage関数でページを追加します。以降の関数は追加後のページに対して処理されます。