ハロの外部記憶インターフェイス

そろそろ覚える努力が必要かも…

CsvHelperを利用して、Csvデータを取り込む

Nugetより、CsvHelperをインストールする。

Csvを読み取り、モデルに設定してくれるパッケージ まあ、便利そうだから入れる。

Csvファイルサンプル

Code,Name
001,Tokyo
002,Osaka
003,Nagoya
004,Hakata
005,Yokohama

Csv取込用モデル作成

Public class MyData {
    Public string Code {get; set;}
    Public string Name {get; set;}
}

Csvファイルを読み取る

Public void main() {
    Dim fs As FileStream = System.IO.File.Open("csv_data\\testcsv.csv", FileMode.Open)

    using(var sr = new StreamReader(fileStream, System.Text.Encoding.GetEncoding("shift_jis"))
    {
        var cr = new CsvHelper.CsvReader(sr);
        While(csvReader.Read()){
             var data = csvReader.GetRecord(Of MyData)()
        }
    }
}

注意点

CsvHelperでモデルにバインドする場合は、ヘッダーにモデルの項目名と一致しないとエラーになるため、注意が必要

SQLCMDでSELECT結果をCSV出力する。

SELECT文の結果をSQLCMDを利用し、CSV出力する

query.sql

クエリを指定したファイル

SET NOCOUNT ON;

SELECT 
       [Code]
      ,[Name]
  FROM [dbo].[Data] ;

SET NOCOUNT ON;を削除すると件数が一緒に出力される。

SQLCMD

query.sqlを読み取り、output.csvファイルへ出力する。

SQLCMD -S localhost -U sa -P {password} -d {dbname} -i query.sql -s, -W -h -1 -o output.csv
  • オプションについて
命令 説明
-S サーバ名
-U ログイン
-P パスワード
-d データベース
-i スクリプトファイル
-s 区切り文字
-W 余計な空白を省く
-h -1でヘッダ非表示
-o 出力ファイル
-v 変数 (param='001' => $(param))

-h オプションについて

-h -1の場合、ヘッダーが一切出力されなくなる。

001,Tokyo
002,Osaka
003,Nagoya
004,Hakata
005,Yokohama

-hオプションなしの場合

Code,Name
----,----
001,Tokyo
002,Osaka
003,Nagoya
004,Hakata
005,Yokohama

ASP.NET MVC FILE UPLOAD

ASP.NET MVCでファイルをアップロードする方法を調べる

以外なところでハマり、悩まされたので、メモる。

Controllerでもファイルの受け取り方法

  • Modelにバインドして取得する。
  • Request.Filesから、inputのnameをキーに取得する。
public ActionResult Upload(FormCollection form)
{
    var file = Request.Files["uploadfile"];
}
もしくは
public ActionResult Upload(MyViewModel model)
{
    model.UploadFile; // -> すでにバインド状態となる。
}

View側での準備

  • formのmethodはPOST
  • formのenctypeは"multipart/form-data" ←これがわからず悩んだ
  • inputのtype=file, name=取得キーもしくはModelの項目名と一致すること
<form method="post" enctype="multipart/form-data">
    <input type="file" name="uploadfile" />
    <button type="submit" > UPLOAD</button>
</form>
もしくは
@Using(Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype="multipart/form-data"})
{
    <input type="file" name="uploadfile" />
    <button type="submit" > UPLOAD</button>
}

ViewModel定義

基本、対象項目の型を”HttpPostedFileBase”にしておくだけ

Public calss MyViewModel
{
    public HttpPostedFileBase UploadFile;
}

ASP.NET MVCでjQueryが動作しない

SCRIPT5009: '$' is not defined

jQueryをすべて正しく設定してもこのエラーになってしまう。

解決

@Scripts.Render("~/bundles/jquery")をヘッダー部に設定する。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - マイ ASP.NET アプリケーション</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")      <!-- 下部にあったjqueryをヘッダー部へ移動した。  -->

</head>
<body>

    // 省略

    @*Scripts.Render("~/bundles/jquery")*@
    @Scripts.Render("~/bundles/bootstrap")

    @RenderSection("scripts", required:=False)
</body>
</html>

Visual StudioのLocalDb管理

LocalDb

Visual Studioから、ローカル用にLocalDbの追加が可能になっている。

※詳細については

SQL Server 2016 Express LocalDB | Microsoft Docs

Visual Studioから追加する。

サンプルプロジェクトはASP.NET MVC Webアプリケーションのルートから、マウス右クリックメニューから「追加」「SQLデータベース」 f:id:haronoid:20180425160022p:plain 新しいDB名を追加 f:id:haronoid:20180425160207p:plain App_Dataフォルダーに追加するか聞かれるが、素直にApp_Dataにしました。 f:id:haronoid:20180425160235p:plain

ソリューションにMyDbが追加される。 f:id:haronoid:20180425160331p:plain

ログインパスワードを設定する。

mdfファイルをダブルクリックするとVisual Studio内のSQL Serverオブジェクトエクスプローラが開きます。

照合順序の変更

デフォルトは「SQL_Latin1_General_CP1_CI_AS」になっており、日本語が文字化けするので、「Japanese_XJIS_100_CI_AI_WS」へ変更が必要

Visual Studio内のSQL ServerオブジェクトエクスプローラからLocalDbを開いて、新しいクエリを表示し、以下のコマンドを実行する。

SELECT DB_NAME()
GO

-- 上記DB_NAMEをDB名にして実行
USE [master]
GO
ALTER DATABASE [database_name] COLLATE Japanese_XJIS_100_CI_AI_WS
GO

テーブルに既にデータが貼っている場合

ALTER TABLE dbo.Table_1 
ALTER COLUMN NAME varchar(50) COLLATE Japanese_XJIS_100_CI_AI_WS;

接続文字列

ASP.NET MVCのプロジェクト内部に入れた場合はフォルダー名を|DataDirectory|にすることが可能

Server=(LocalDB)\MSSQLLocalDB; Integrated Security=true ;AttachDbFileName=D:\Data\MyDB1.mdf
Server=(LocalDB)\MSSQLLocalDB; Integrated Security=true ;AttachDbFileName=|DataDirectory|MyDB1.mdf

MS SQL Server Management Studioから接続する。

接続文字列に(LocalDB){インスタンス名}で接続出来る。

(LocalDB)\MSSQLLocalDB

インスタンス名がわからない場合、「sqllocaldb.exe」で調べられる。

> sqllocaldb info
MSSQLLocalDB
ProjectsV13

sqlcmdで接続する場合

新しいDB作成及び、ログインの手順…

恐らく、LocalDbをサーバーリリスする場合、サーバーのローカルユーザーからLocalDbを作成しないと権限問題が発生する可能性があり、 以下のコマンドからサーバーでLocalDbを作成するコマンドを実行する必要がありそう。 サーバーにもSQL Server Express LocalDbをインストールする必要あり。

SqlLocalDB.exe create "DeptLocalDB"  
SqlLocalDB.exe share "DeptLocalDB" "DeptSharedLocalDB"  
SqlLocalDB.exe start "DeptLocalDB"  
SqlLocalDB.exe info "DeptLocalDB"  
REM The previous statement outputs the Instance pipe name for the next step  
sqlcmd –S np:\\.\pipe\LOCALDB#<use your pipe name>\tsql\query  
CREATE LOGIN NewLogin WITH PASSWORD = 'Passw0rd!!@52';   
GO  
CREATE USER NewLogin;  
GO  
EXIT  
sqlcmd –S (localdb)\.\DeptSharedLocalDB -U NewLogin -P Passw0rd!!@52  

参考: SqlLocalDB ユーティリティ | Microsoft Docs

ダウンロード: SQL Server Downloads | Microsoft

ASP.NET MVC画面イメージをPDFにする。

ASP.NET MVCの画面をPDF化する方法

ASP.NET MVCでの帳票関連で使えるのがないか調べている内に見つかった。もので、画面イメージをそのままPDF化出来るものがあったので、メモる。

TuesPechkin

wkhtmltopdfをベースにラッピングしている模様。注意としてwkhtmltopdfがAzureでは動作しないみたいで、Azureで使用するなら別の方法を考えた方がいいかも GitHub - tuespetre/TuesPechkin: A .NET wrapper for the wkhtmltopdf library with an object-oriented API.

Nuget

Nugetからインストールする。Win32と64がそれぞれあるけど、AnyCPUで問題なかった。

PM> Install-Package TuesPechkin.Wkhtmltox.AnyCPU

Controller

pdf化したい画面をUrlにし、HtmlToPdfDocumentに渡せば基本簡単に出来ちゃう感じです。 ASP.NET MVCでやっているが、MVCは特に関係なさそう。

using TuesPechkin;

public class HomeController : Controller
{
    public ActionResult ToPdfPage()
    {
        var helper = new UrlHelper(ControllerContext.RequestContext);
        var indexUrl = helper.Action("Index", "Home", null, Request.Url.Scheme);

        var document = new HtmlToPdfDocument()
        {
            GlobalSettings =
            {
                ProduceOutline = true,
                DocumentTitle = "PDF Sample",
                PaperSize = PaperKind.A4,
                Margins =
                {
                    All = 1.375,
                    Unit = Unit.Centimeters
                }
            },
            Objects =
            {
                new ObjectSettings() {
                    PageUrl = indexUrl,
                },
            }
        };

        var converter = new StandardConverter(
                    new PdfToolset(
                        new WinAnyCPUEmbeddedDeployment(
                            new TempFolderDeployment())));

        var pdfData = converter.Convert(document);

        return File(pdfData, "application/pdf", "PdfSample.pdf");
    }
}

ExcelファイルをPdfに変換する。

前提条件

  • 実行するサーバーのExcelアプリを実行するため、サーバーにExcelのインストールが必要
  • バージョンは2007以降である必要
  • .NETのアセンブリを利用するため、Windowsサーバー限定となる。

Visual Studioでプロジェクトを生成し、参照を追加

Nugetで以下のパッケージを追加します。 * Microsoft.Office.Interop.Excel

using

オープンするオブジェクトはすべて「ComObject」になるらしく、いちいち開放してあげないとプロセスが残ってしまう。

using Microsoft.Office.Interop.Excel;  // Excel関連
using System.Runtime.InteropServices;  // ComObjectを開放するため

ExcelファイルのOpen

private Application _application = new Application();
private Workbook _workbook;
_application.Visible = false;   // Excel Window 非表示
_workbook = (Workbook)_application.Workbooks.Open(filepath);

ExcelをPdf出力する

そなえつけの「ExportAsFixedFormat」関数でExcelのPdf出力は簡単に出来た。

_workbook.Worksheets.Select(); // 全シート選択状態

_workbook.ExportAsFixedFormat(
     XlFixedFormatType.xlTypePDF,    //XPSとPDFのどれか
     pdfFilePath,                                     //PDFファイルの出力パス
     XlFixedFormatQuality.xlQualityStandard);   //品質:StandardとMinimumのみ

ComObjectの開放

面倒だったのが、SheetもCellもつくたびComObjectの参照カウントが増えるため、任意に解除する必要があった。

public void SetWorkSheet(int sheetNo)
{
    Marshal.ReleaseComObject(_worksheet);
    _worksheet = _workbook.Worksheets.Item[sheetNo];
}
public string GetCellText(int rowNo, int colNo)
{
    string ret;
    var cell = _worksheet.Cells[rowNo, colNo];
    ret = cell.Text;
    Marshal.ReleaseComObject(cell);
    return ret;
}
public void Close()
{
    if (_worksheet != null)
    {
        Marshal.ReleaseComObject(_worksheet);
        _worksheet = null;
    }
    if (_workbook != null)
    {
        _workbook.Close(false); // 変更分を保存せず終了する。
        Marshal.ReleaseComObject(_workbook);
        _workbook = null;
    }
    if (_application != null)
    {
        _application.Quit();
        Marshal.ReleaseComObject(_application);
        _application = null;
    }
}

作ったソースの中から、一部メモとして残す。

最終的に

ComObject開放がうまくいかなかったり、プロセスが残ったりしたので、Excelの操作系はClosedXMLを利用することにした。