だら$ちっぷす

仕事の覚書です

C#はじめました。Excelを使う。

しまった。。。スクショは撮ったのに書くの忘れててあんま覚えてない。変なとこあるかも。。。と思いつつ、まとめる。


Excelを使いたいので調べる。

とりあえず、ぐぐって先頭に出てきた本家Microsoftがおすすめする、Microsoft Excel ObjectLibraryを入れてみる。
けど、これだとだめだわーということに気づく。なにがだめだと思ったのか覚えてないんやけど。。。(^^;
なんやったかなあ?DBで取ってきたデータを貼り付けようとしてrangeで書き込む方法探してたらみつからなくて、代わりにrangeで書き込めないと書かれてるのを見つけたとか、そういうことだったと思います。

とりあえず、そんな感じで、他を探す。

ClosedXML
NPOI

このどっちかがよさそう。
使いやすいのはClosedXMLだけど、グラフ生成機能がないのが難点らしい。
NPOIは多機能だけどクセがすごいんじゃー!らしい。
今回はグラフは外からは作らない方針なので、ClosedXMLをインストールしてみる。


<大事!!>
以下、自分がやった履歴を書いてますが、後から見るとやらんでええことをいろいろやっています。
以降、赤字で書いてるとこは、多分、いらんことやと思います。


ClosedXMLは、NuGetからインストールするらしい。

ツール→NuGetパッケージマネージャ→パッケージマネージャコンソール


パッケージマネージャコンソール→パッケージソース→Microsoft Visual Studio Offline→nuget.org



パッケージマネージャコンソールから、closedXMLインストールを指示するらしい。

なんかエラー出たー(つ﹏<)・゚。


「install」「-package」 じゃなくて、「install-Package」なのねー。
意外と、ここで時間くったw

またエラー出たー(つ﹏<)・゚。



パッケージソースをnuget.orgに変更しなきゃですね。
よく気がついた!わたし!σ-`д・´)☆



なんかまだ怒られる・3・
SixLabord.Fontsてなんやねん。


なんか、コマンドラインからじゃなくて、パッケージマネージャとやらからインストールしてはる人を見かけたので、そっち試してみる。

とりあえず、今、ごちゃごちゃ入れたのをクリアする。

ツール→オプション

NuGetパッケージマネージャ→全般→規定のパッケージ管理形式→PackageReference


NuGetパッケージマネージャ


NuGet・ソリューション→ClosedXML


プロジェクトにチェックを入れてインストール


まだ文句いわれてるー(つ﹏<)・゚。



いっぺん、パッケージをクリアしてからやりなおせって書いてるのを見たのでクリアしてみる。



もっぺんインストールしてみたら、上のエラーは消えたけど、SixLabord.Fontsのエラーは相変わらず残っている。





さらから始めるんやったら、ここからスタートでOK!やと思う!多分!


SixLabord.Fontsを個別でインストールしないとだめらしい。



なんかキター!



同意します!



closedXMLを再再再度?インストール!!



同意します!



やった!!遂に、インストール成功!!✧。٩(ˊᗜˋ)و✧*。



こんな感じのプログラムでExcelファイルの作成に成功しましたよ。(๑•̀⌄ー́๑)b

using ClosedXML.Excel;

・・・

        private void btn_excel_Click(object sender, EventArgs e)
        {
            using var wb = new XLWorkbook();
            var ws = wb.Worksheets.Add("シート1");

            ws.Range(1, 1, 10, 10).SetValue("(∩´∀`)∩");

            wb.SaveAs(@"test.xlsx");
        }

C#はじめました。postgreSQLに繋ぐ

postgreSQLをインストールしました。

適当にテーブル作りました。

ツールボックスからDataGridViewというのをFormに貼り付けました。
ここにDBから読み込んだデータを表示したいと思います。


ソース、こんなかんじ

using Npgsql; 

・・・

        private void btn_DBconnect_Click(object sender, EventArgs e)
        {
            try
            {
                // 接続文字列
                var conStr = "Server=localhost;Port=5432;Username=postgres;Password=daradara;Database=test";
                using NpgsqlConnection con = new(conStr);
                con.Open();

                using NpgsqlCommand cmd = new();
                cmd.Connection = con;

                for (int i = 0; i < 3; i++)
                {
                    //データを作る
                    cmd.CommandText = $"INSERT INTO syain(name, birthday) VALUES ('社員{i}', '{DateTime.Now}');";
                    ret = cmd.ExecuteNonQuery();
                }

                //データを読み込む
                IDataAdapter dataAdapter = new NpgsqlDataAdapter("select * from syain", con);
                var dataSet = new DataSet();
                dataAdapter.Fill(dataSet);

                //グリッドにデータセットをリンク
                this.dataGridView1.DataSource = dataSet.Tables[0];
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }


エラー出た(><;
なんかバージョン古いて言われてる。



shincode.info
要は、プロジェクトファイルを書き換えればいいってことね。
というわけで、ソリューションの下のプロジェクトの下に「.csproj」ていう拡張子のファイルがあるんで、それをエディターで開いて、LangVersionを書き加えてやる。
8.0以上を使え言うてるやつと、9.0以上使え言うてるやつの2つがあるので、9.0にしてみる。



VisualStudio再起動。

エラー出やんと走ったー。(´∀`*)



他のマシンからもDB参照できるようにする。

postgresweb.com
C:\Program Files\PostgreSQL\15\data を開いて、

postgresql.conf を書き換え。

# - Connection Settings -

listen_addresses = '*'  # what IP address(es) to listen on;
                    # comma-separated list of addresses;
                    # defaults to 'localhost'; use '*' for all
                    # (change requires restart)


pg_hba.conf に下の1書き加え。

# IPv4 local connections:
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             0.0.0.0/0            scram-sha-256   # 2023-08-07 追記



postgreSQL再起動(。。。すんのなんかめんどいからマシン再起動した)

OK!^^

C#はじめました。まずはフォーム画面を作ってみる。

C#はじめます。

まずは何をすればええのじゃー。
まったく何もしりません。(C使い、Delphi使いではあります)

調べてみたところ、C#.Net Framework 上で動くらしい?
.Net Frameworkは、winidowsマシンやったら気にせんでも入ってるらしい?
C#Visual Studioで開発するといいらしい?
Visual Studioを入れると、C#も入るらしい?

てなわけで、Visual Studio2022を入れてみました。

learn.microsoft.com
まずはフォーム画面を作ってみよう。

learn.microsoft.com
うーん?
Windowsフォームアプリ」と「Windowsフォームアプリケーション (.NET Framework)」てのがあるけど、どっちを選べばいいのかなあ?
上記、レッスンでは「アプリケーション」の方やけど、自分の目的と合ってるのかなあ?

impsbl.hatenablog.jp
こちらの記述がわかり易かったです!
素直に「Windowsフォームアプリケーション (.NET Framework)」を選ぼうと思います!

新規ソリューションを作った。




上記、MSのサイトに書かれてる通りにやってみます。


(・3・) ツールボックス、どこにあんの?


左の赤丸「ツールボックス」をクリックして、右の赤丸「ピンを刺して」、真ん中の赤丸「コモンコントロール」の下が、画面に貼り付けられる部品です。


(・3・) プロパティ、どこにあんの?


「表示」→「プロパティウィンドウ」


(・3・) 実行メニュー、どこにあんの?


なんか、右の赤丸のとこ、ピッてやったら出た!!
わからんわそんなもん!!><、、、


作った!!



走らした!!


perplexity.ai が良いと聞いたので。後、chrome拡張の追加の仕方。

perplexity.ai が良いと聞いたので試してみようと思った。
でも、どうやったら使えるの?
全然わからないのでぐぐってみたらChromeに入れろって書いてある。
なんかchrome検索エンジンに追加したら良いとか。。。
書かれてる通りにやってみたが、書かれてるようにうまくいかない・3・
うーん・・・
初心に戻って(初心なかったんですけど)googleさんで「perplexity.ai」て検索してみた

perplexity.ai

普通にperplexity.aiのサイトに飛ぶよねーw
そらそうや。変なとこから入ったから考えてなかった。申し訳ない。
いや、githubとかそういうやつかなーと思ってたんで手順サイトで教えてもらった方が早いかと思って。。。すみません><;

このまま使ってもええんやけど、なんかクロム拡張が用意されてるみたいなんで、せっかくなので入れてみることにした。初心貫徹?(違w)

右上の「chrome extension」をクリック




ウェブストアサイトに飛ばされる。ここで「chromeに追加」




拡張しますか?と聞かれるので「拡張機能を追加」する



追加されましたー。簡単簡単^^




追加したけど、どうやって使うの?(・・?
ようわからんので、上んとこにアイコンを表示しとくことにしましたー^^;

これを。。。

こうじゃ!


後は、アイコンをクリックしたら検索画面がぺろーんと出てくるんで質問を入力する
こんな感じー



でも、これだと、普通にperplexity.aiのサイトで検索するんとあんま変わりないよね?
なんかユーザ数少なくない?って思ったんだけど、そういうことかなー?
まあ、いいや。
とりま、色々使ってみますー^^


Node.jsでローカルサーバを立てる

ちょっとしたwebツールを作るのにファイル操作めんどいからnodeでやったれと思って久々にメインから書きはじめたら全然忘れてた(;´д`)のでメモ。

/*
  tool1.js
  起動テスト
*/

//起動アドレス
const ip = "127.0.0.1";    //localhost
const port = 30303;   //テキトー(未だに何番使えば笑われなくて済むのかわからん)

//expressモジュール
const express = require('express');
const app = express();

//appでjson送る時はこの2つが必要(送れるサイズをでかくする。デフォルトは100kb)
app.use(express.json({ extended: true, limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));


//https鯖を起動
try
{
    app.listen(port, ip, () =>
    {
        console.log('http server ' + ip + ":" + port)
    });
}
catch(err)
{
    console.log("鯖起動エラー", err);
    process.exit(1);
}

//確認
app.get('/', async (req, res, next) => 
{
    res.send('動作確認。わたしの好きな言葉です^^');
});



これを起動

>node tool1.js
http server 127.0.0.1:30303



ブラウザで表示

URL[ http://localhost:30303 ]
動作確認。わたしの好きな言葉です^^



よしよし。ええ感じや^^

続けて、POSTのテストをします。
以下のルーチンを tool1.js に追加。

//POST確認
app.post('/situmon', async (req, res, next) => 
{
    let ans = {};
    switch(req.body.situmon)
    {
        case "like":
            ans.kotae = "動作確認。わたしの好きな言葉です^^";
            break;
        case "hate":
            ans.kotae = "仕様変更。わたしの苦手な言葉です><";
            break;
        default:
            ans.kotae = "・・・・・(V)o\\o(V)ふぉっふぉっふぉ";
    }
    res.setHeader('Content-Type', 'application/json');
    res.write(JSON.stringify(ans));
    res.end();
});



POSTはfetchで発行するんで、少々テストがめんどいっす><;
こんなHTMLを作ってみました。

<!DOCTYPE html>
<html>
<!------------------------------------------------------------------------------
    test1.html
-------------------------------------------------------------------------------->
<head>
    <meta charset="UTF-8">
    <title>test1</title>
    <style>
        div > div
        {
            display: flex;              /*センタリング */
            align-items: center;        /*センタリング */
            justify-content: center;    /*センタリング */
            background-color:#fffaf0;
            border: solid #4682b4;
            border-radius: 8px;
            cursor:pointer;
            margin-top:8px;
            width:100px;
            height:30px;
            margin: 50px 2px 0px 2px;
        }
    </style>
</head>
<body>
    <div style="display:flex;justify-content: center;align-items: center;">
        <div onClick="situmon('like')">好きな言葉</div>
        <div onClick="situmon('hate')">苦手な言葉</div>
        <div onClick="situmon('')">無言</div>
    </div>
    <div id="id_kotae">
        <!-- ここに回答を書く -->
    </div>
</body>
</html>

<script>
async function situmon(word)
{
    let str = "";

    try
    {
        //送るデータ
        let reqData = 
        {
            situmon:    word
        };

        //送受信
        const res = await fetch(
                        "http://localhost:30303/situmon", 
                        {
                            method:     'POST',
                            body:       JSON.stringify(reqData), 
                            headers:    {'Content-Type': 'application/json'}
                            credentials:'include',
                            mode:       'cors'
                        });
        //受けたデータ
        if(res.ok)
        {
            const resData = await res.json();
            str = resData.kotae;
        }
        else
        {
            str = "[POST ERROR] " + res.statusText;
        }
    }
    catch(err)
    {
        str = "[FETCH ERROR] " + err;
    }

    id_kotae.innerHTML = str;
}
</script>



test1.htmlをダブルクリックするとchrome画面が立ち上がる。(うちはwindowschrome使てますからー)
適当なボタンをポチッとな。

・・・・ぐあああああああ!!!!::: (ノ'A`)>:::
出たなーーー!!!クロスオリジンめーーーーー!!!!!=͟͟͞͞⊂( ‘ω’∩ )

fetch使たらクロスオリジンでるんやったっけ。ちぇ。・3・
test1.jsに以下の2行を付け加える。

//https鯖を起動
try
{
    //CORSを許可する(fetchを使うために必要)
    const cors = require('cors');
    app.use(cors({ origin: true, credentials: true }));


    app.listen(port, ip, () =>
    {
        console.log('http server ' + ip + ":" + port)
    });
}
catch(err)
{
    console.log("鯖起動エラー", err);
    process.exit(1);
}



よし!再起動だ!(`・ω・´)ゞ
再起動。わたしの好きな言葉です。
HTMLをダブルクリックして、ボタンポチ~( ・∀・)つ〃∩


うまく行ったー!!(∩´∀`)∩ワーイ(∩´∀`)∩ワーイ

以上です!(`・ω・´)ゞ
※これはローカル専用です。セキュリティもへったくれも考えてないです。

Node.js でURLの引数とか

多分めっちゃ初歩的なことなんだけど、毎回忘れてぐぐるんで、ここに書いておく

こういうURLのとき
https://~~~/page?user_id=[A]&user_name=[B]

router.get('/', async (req, res) =>
{
    if(req.query.user_id == undefined)
    {
        console.log("エラーですやん");
        return;とか
    }
    var user_id = req.query.user_id;

    if(req.query.user_name == undefined)
        var mode = "ななしー";
    else
        var mode = req.query.user_name;
});



こういうURLのとき
https://~~~/page/[A]/[B]

router.get('/:user_id/:user_name', async (req, res) =>
{
    if(req.params.user_id == undefined)
    {
        console.log("エラーですやん");
        return;とか
    }
    var user_id = req.params.user_id;

    if(req.params.user_name == undefined)
        var mode = "ななしー";
    else
        var mode = req.params.user_name;
});

あー。なんか、一番上からの:はあかんみたい。そらそうか。全部になってまうもんなー。

わかった!! 一番上からの:があかんのではなくて、2つとも:だと、何もかもになってしまうのでだめでした

こういうURLだったらいける
https://~~~/page/[A]/user_name

router.get('/:user_id/user_name', async (req, res) =>
{
    if(req.params.user_id == undefined)
    {
        console.log("エラーですやん");
        return;とか
    }
    var user_id = req.params.user_id;

});

node.js セッション ログイン状態を持続する

いっぺんログインしたクライアントは2回め以降ログインせんでもいけるようにしてーと言われたので調べた
(のを書いてなかったみたいなので書いとく。1年前のやつですが今んとこまだ使えてます)

セッションを定義して、サーバを起動する(日本語変かもー)

   //CORSを許可する
    const cors = require('cors');
    app.use(cors({ origin: true, credentials: true }));

    //セッション定義
    const session = require('express-session');
    var sess = 
    {
        secret:             'keyboard cat',
        resave:             false,
        saveUninitialized:  false, 
        cookie: 
        {
            maxAge:     24 * 60 * 60 * 1000,    //1日有効 
            sameSite:   'none',
            secure:     true       //←httpsのときしかクッキーを通さないモード
                                 //  これをtrueにしておかないとchromeでエラーになる
        }
    };
    app.use(session(sess));


    //session(cookie)を使うためにhttpsにする
    const fs = require('fs');
    const options = 
    {
        key:    fs.readFileSync('xxx.key'),    //セキュリティ証明書
        cert:   fs.readFileSync('xxx.crt')      //KEYファイル
    };
    const https = require('https');
    const server = https.createServer(options, app);
    server.listen(3000, () => 
    {
        console.log('https server listening port 3000')
    });


セッションって、クッキー使ってやるのねー。しらんかったー(^^;
クライアント側、ログイン要求。こんな感じで。

   data.name = "ログイン名";
    const res = await fetch("https://localhost:3000/login",
            {
                method:     'POST',
                body:       JSON.stringify(data), 
                headers:        {'Content-Type': 'application/json'},
                credentials:    'include',
                mode:       'cors'
            });


サーバ側、ログイン受信処理

router.post('/login', async (req, res, next) => 
{
    //セッションにセット
    req.session.login = 
    {
        user_name:  req.body.name
    };
    res.end();
}


サーバ側、以降、必ずログイン名がくっついて来る

router.post('/nanka_suru', async (req, res, next) => 
{
    if (req.session != undefined && req.session.login != undefined)
        console.log(req.session.login.user_name);  //ログイン名
    res.end();
});


ログアウトのときは、無効な値をセットしておけばよい
以下のようにしておけば、次に nanka_suru が呼ばれたときに、req.session.login == undefined になって、ログインしてないことがわかる

router.post('/logout', async (req, res, next) => 
{
    if (req.session != undefined && req.session.login != undefined)
        req.session.login = undefined;
    res.end();
});


なんか特別なログイン・ログアウトの仕組みがあるんかと思ってたけど、普通に自分でやればいいだけだったみたい^^