SQLの窓

2018年06月20日


C# と VB.net : TKMP.DLL を使って IMAP でメール本文の一覧を取得する( コンソール )

※ 重要
Gmail では安全性の低いアプリの許可を『有効』にする必要があります

.NET用メール送受信クラスライブラリ (TKMP.DLL) 
※ 2011-10-01 時点で 3.0.1
※ 2018-06-20 時点で 3.1.8( 2017/02/15 作成 )

TKMP は、VB.net や C# から日本語環境を気にしないでメールの送受信が行える貴重なライブラリですが、IMAP に対応しておられるのに添付されているドキュメントや、WEB 上のサンプルコードにその記述がありませんでしたので作成しました。

※ IMAP は 2011/08/11 に対応されています。
オンラインドキュメント

C#
using System;
using TKMP.Net;
using TKMP.Reader;

namespace MailRecTestCs
{
    class Program
    {
        static void Main(string[] args)
        {
            // IMAP 用基本認証
            BasicImapLogon logon = new BasicImapLogon("アカウント", "パスワード");
            // IMAP 用ログイン( 993 は、SSL 用 )
            ImapClient client = new ImapClient(logon, "サーバードメイン", 993);

            // SSL で接続する
            client.AuthenticationProtocol = AuthenticationProtocols.SSL;

            // 接続
            client.Connect();

            // メールデータ一覧の取得
            IMailData[] md_i = client.GetMailList();

            // メールデータの数
            Console.WriteLine(md_i.Length);

            // メールデータの本文を取得
            MailReader reader = null/* TODO Change to default(_) if this is not a reference type */;
            System.IO.Stream Body_data = null;

            // 全て表示
            for (int i = 0; i <= md_i.Length - 1; i++)
            {

                // メッセージを読み込む( 同期処理 )
                md_i[i].ReadBody();

                // 読み出しの為にストリームを取得
                Body_data = md_i[i].DataStream;

                // メールリーダで本文を解析
                reader = new TKMP.Reader.MailReader(Body_data, false);

                // マルチパートの時は最初に見つかったテキストセクションの本文
                Console.WriteLine(reader.MainText);

                // ヘッダ情報の取得
                foreach (TKMP.Reader.Header.HeaderString headerdata in reader.HeaderCollection)
                {
                    if (headerdata.Name == "From")
                        Console.WriteLine(string.Format("From : {0}", headerdata.Data));

                    if (headerdata.Name == "Subject")
                        Console.WriteLine(string.Format("Subject : {0}", headerdata.Data));

                    if (headerdata.Name == "Date")
                    {
                        Console.WriteLine(string.Format("Date オリジナル : {0}", headerdata.Data));
                        string target = headerdata.Data;
                        // 日付データの最後に(おそらく)改行が含まれていたので (JST) + 1 で6バイト除去しています
                        target = target.Substring(0, target.Length - 6);
                        try
                        {
                            DateTime dt = System.DateTime.ParseExact(target, "ddd, d MMM yyyy HH':'mm':'ss zzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None);
                            Console.WriteLine(string.Format("Date : {0}", dt));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("フォーマット変換できませんでした");
                        }
                    }
                }
            }

            // 接続解除
            client.Close();

            Console.ReadLine();
        }
    }
}

VB.net
Imports TKMP.Net
Imports TKMP.Reader

Module Module1

    Sub Main()

        ' IMAP 用基本認証
        Dim logon As BasicImapLogon = New BasicImapLogon("アカウント", "パスワード")
        ' IMAP 用ログイン( 993 は、SSL 用 )
        Dim client As ImapClient = New ImapClient(logon, "サーバードメイン", 993)

        ' SSL で接続する
        client.AuthenticationProtocol = AuthenticationProtocols.SSL

        ' 接続
        client.Connect()

        ' メールデータ一覧の取得
        Dim md_i As IMailData() = client.GetMailList()

        ' メールデータの数
        Console.WriteLine(md_i.Length)

        ' メールデータの本文を取得
        Dim reader As MailReader = Nothing
        Dim Body_data As System.IO.Stream = Nothing

        ' 全て表示
        For i As Integer = 0 To md_i.Length - 1

            ' メッセージを読み込む( 同期処理 )
            md_i(i).ReadBody()

            ' 読み出しの為にストリームを取得
            Body_data = md_i(i).DataStream

            ' メールリーダで本文を解析
            reader = New TKMP.Reader.MailReader(Body_data, False)

            ' マルチパートの時は最初に見つかったテキストセクションの本文
            Console.WriteLine(reader.MainText)

            ' ヘッダ情報の取得
            For Each headerdata As TKMP.Reader.Header.HeaderString In reader.HeaderCollection

                If headerdata.Name = "From" Then
                    Console.WriteLine(String.Format("From : {0}", headerdata.Data))
                End If

                If headerdata.Name = "Subject" Then
                    Console.WriteLine(String.Format("Subject : {0}", headerdata.Data))
                End If

                If headerdata.Name = "Date" Then
                    Console.WriteLine(String.Format("Date オリジナル : {0}", headerdata.Data))
                    Dim target As String = headerdata.Data
                    ' 日付データの最後に(おそらく)改行が含まれていたので (JST) + 1 で6バイト除去しています
                    target = target.Substring(0, target.Length - 6)
                    Try
                        Dim dt As DateTime = System.DateTime.ParseExact(target, "ddd, d MMM yyyy HH':'mm':'ss zzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
                        Console.WriteLine(String.Format("Date : {0}", dt))
                    Catch ex As Exception
                        Console.WriteLine("フォーマット変換できませんでした")
                    End Try
                End If
            Next

        Next

        ' 接続解除
        client.Close()

        Console.ReadLine()

    End Sub


End Module

関連する Microsfot のドキュメント

POP3 アクセス用および IMAP4 アクセス用の TLS と SSL の構成: Exchange 2010 SP1 のヘルプ




posted by lightbox at 2018-06-20 11:05 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2018年06月12日


C# でDataTable と DataSource を使用して、DataGridView にデータを表示するテンプレート( 行をダブルクリックしてダイアログを表示して行データを処理 )



画面はメインとなる DataGridView を最初に作成して Dock を Fill にします。Fill を設定したコントロールの上下にコントロールを使用する場合は、レイアウトは見たままでは無く Fill にしたものを一番上に置いて他のコントロールを下にします。



ステータスバー、ツールバー、メニューバーと順序が見ている位置と逆にして、それぞれの Dock プロパティを設定します。( ステータスとメニューはデフォルトで OK )

DataGridView のプロパティは重要なので以下に設定内容を自動作成されたコードで示します
            this.dataGridView1 = new System.Windows.Forms.DataGridView();

            this.dataGridView1.AllowUserToAddRows = false;
            this.dataGridView1.AllowUserToDeleteRows = false;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataGridView1.Location = new System.Drawing.Point(0, 49);
            this.dataGridView1.MultiSelect = false;
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.ReadOnly = true;
            this.dataGridView1.RowTemplate.Height = 21;
            this.dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
            this.dataGridView1.Size = new System.Drawing.Size(813, 407);
            this.dataGridView1.TabIndex = 0;
            this.dataGridView1.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellDoubleClick);

            public System.Windows.Forms.DataGridView dataGridView1;
ハイライトの行は、最初に設定する3つの編集を許可するかどうかのプロパティで、全て使用不可にしています。

1) 選択は単一行にする : MultiSelect = false
2) 選択表示は行全体にする : SelectionMode = FullRowSelect
3) 行のダブルクリックイベントは、CellDoubleClick で行う
4) Form2 から直接参照可能なように、public で定義する( Modifiers = Public )

次に、Form1 のソースコードですが、表示するデータは環境変数の一覧を使用しています( 実際に変更せずに DataGridView にデータを戻すまでの処理を行います )
    public partial class Form1 : Form
    {
        private DataTable table;
        private DataColumn column;
        private DataRow row;
        private Form nextWindow;

        public Form1()
        {
            InitializeComponent();
        }

        // ツールバーのボタンをクリック
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            // DataTable の作成
            table = new DataTable("EnvironmentVariables");

            // 列情報 の作成
            column = new DataColumn();
            column.DataType = Type.GetType("System.String");
            column.ColumnName = "環境変数";
            table.Columns.Add(column);

            // 列情報 の作成
            column = new DataColumn();
            column.DataType = Type.GetType("System.String");
            column.ColumnName = "値";
            table.Columns.Add(column);

            // 環境変数一覧より、行情報の作成
            foreach (DictionaryEntry dict in Environment.GetEnvironmentVariables())
            {
                row = table.NewRow();
                row["環境変数"] = dict.Key;
                row["値"] = dict.Value;
                table.Rows.Add(row);
            }

            // データーソース経由で DataGridView を表示
            dataGridView1.DataSource = table;
            // 第一カラムでソート
            dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
            // 自動整列
            dataGridView1.AutoResizeColumns();

        }

        // 行をダブルクリックしてダイアログを表示
        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            int rowNumber = e.RowIndex;
            if (rowNumber < 0 ){
                return;
            }

            // 行=>列=>からの参照
            string value = dataGridView1.Rows[rowNumber].Cells["値"].Value.ToString();
            Console.WriteLine(value);

            // モーダルダイアログとして開く
            using (nextWindow = new Form2(rowNumber))
            {
                nextWindow.ShowDialog(this);
            }

        }
    }


DataTable の考え方は、SQL 文の cerate tableを実行して列の定義を行った上で、テーブルに行を追加して行くというものです。そのテーブル情報全てを DataSource にセットする事で DataGridView への表示が完了します。

※ 列のタイトルは、ColumnName にセットされた内容が表示されます

そして、行をダブルクリックして 行=>列=>からの参照でデータを取得していますが、ここでは確認の為に表示しているだけで、実際は Form2 から直接に [列,行] という形で参照しています。
    public partial class Form2 : Form
    {
        private int rowNumber;
        private DataGridView grid;

        // コンストラクタで処理する行を渡す
        public Form2(int rowNumber)
        {
            this.rowNumber = rowNumber;
            InitializeComponent();

        }

        // データ変更ボタンで親内の DataGridView を直接変更
        private void button1_Click(object sender, EventArgs e)
        {
            grid["値", rowNumber].Value = textBox2.Text;
            grid["値", rowNumber].Style.BackColor = Color.Pink;

            Console.WriteLine("表示データを書き換えました");
            this.Close();
        }

        // キャンセル( フォームのデフォルトボタン )
        private void button2_Click(object sender, EventArgs e)
        {
            Console.WriteLine("キャンセルされました");
            this.Close();
        }

        // 初期フォーカス
        private void Form2_Shown(object sender, EventArgs e)
        {
            textBox1.Focus();

        }

        // 親フォームからの情報を取得
        private void Form2_Load(object sender, EventArgs e)
        {
            grid = ((Form1)Owner).dataGridView1;
            textBox1.Text = grid["環境変数",rowNumber].Value.ToString();
            textBox2.Text = grid["値",rowNumber].Value.ToString();

        }
    }

親フォームの参照は、Owner プロパティを使用し、初期フォーカスの設定を Shown イベントで行うのが重要です。




posted by lightbox at 2018-06-12 12:42 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2018年01月23日


(C#) / VS2010 または VS2012 : TKMP.DLL(3.1.2 または 3.1.8)を使った、『さくらインターネット』用メール送信テンプレート



OneDrive よりダウンロード

テンプレートには、3.1.2 が入っていますが、Windwos10(64) + Visual Studio 2012 C# でテスト(2018-01-23)しました。


さくらインターネット

現在スタンダードを運用していますが、月額 515円 容量 100GB です

メールメールアドレスを無制限で作成できます(当然容量内ですが)。
メールボックスの容量を1MBから2048MBまで任意に指定できます。
※ サーバのディスク容量がひっ迫していると、しきい値内であってもメールは届きません。
ウェブメール ※ 一応あります( そんなに力を入れてるとは思えないです ) ❸ メーリングリストは10個 コスト 月額515円 ( 年間一括支払いの場合、5,142円 ) レンタルサーバーとしては、さくらのブログの内容が Seesaa ブログの劣化版である事をのぞけば、結構いたれりつくせりだと思っています。 基本仕様一覧 Ruby は 1.8.x なんで、ちょっと古いと思っています。 データベース使用量は、こんなふうに昔から記述されています。
基本的に制限は設けておりませんが、共用データベースサーバでは使用量の目安がございます。
目安以上の容量を使用された場合、他のお客様への影響がでたり、障害が発生した場合、データの復旧が正常に行えない 可能性がございます。
SSL は 共有SSL が使えます。気軽にログイン部分等、暗号化可能です。 CRONの設定数は 5 です
MailClass mc = new MailClass()
{
    SmtpServer = "初期ドメイン",
    Port = 587,
    User = "ユーザ名@ドメイン",
    Pass = "パスワード",
    Protocol = AuthenticationProtocols.TLS
};

var result = mc.SendMail(
    "宛て先",
    "ユーザ名@ドメイン",
    this.subject.Text,
    this.body.Text,
    null,   // 必要な場合、宛先を日本語で
    null,   // 必要な場合、差出人を日本語で
    (MailClass.MailClassErrorArg _e) =>
    {
        this.error.Text = _e.Message;
    }
);

MailClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TKMP.Writer;
using TKMP.Net;

namespace TKMP_SendMail_Sakura1 {
	class MailClass {
		private MailWriter mw = null;

		public string SmtpServer { get; set; }
		public int Port { get; set; }
		public string User { get; set; }
		public string Pass { get; set; }
		public AuthenticationProtocols Protocol { get; set; }

		private string err_message = "";

		public class MailClassErrorArg {
			public string Message { get; set; }
		}

		public delegate void MailClassError(MailClassErrorArg e);

		public bool SendMail(string To, string From, string Subject, string Body, string To_J, string From_J, MailClassError mce) {
			bool bResult = true;

			mw = new MailWriter();

			try {
				mw.ToAddressList.Add(To);
			}
			catch (Exception ex) {
				bResult = false;
			}
			if (!bResult) {
				if (mce != null) {
					MailClassErrorArg e = new MailClassErrorArg() { Message = "宛先が正しくありません" };
					mce(e);
				}
				return bResult;
			}

			// From が未指定や正しくない文字列の場合
			try {
				mw.FromAddress = From;
			}
			catch (Exception ex) {
				// ユーザが正しければ、以下のように設定しても『ユーザ名 <メールアドレス>』に変換される
				mw.FromAddress = "______@hotmail.co.jp";
			}

			TextPart tp = new TextPart(Body);
			mw.MainPart = tp;

			if (To_J != null) {
				mw.Headers.Add("To", To_J + " <" + To + ">");
			}
			else {
				mw.Headers.Add("To", To);
			}
			if (From_J != null) {
				mw.Headers.Add("From", From_J + " <" + From + ">");
			}
			else {
				// Hotmail では、自動的に 『ユーザ名 <メールアドレス>』に変換される
				mw.Headers.Add("From", From);
			}

			mw.Headers.Add("Subject", Subject);
			mw.Headers.Add("X-Mailer", "TKMP Version 3.1.2");

			var logon = new TKMP.Net.AuthLogin(User, Pass);
			SmtpClient sc = new SmtpClient(SmtpServer, Port, logon);
			sc.AuthenticationProtocol = Protocol;

			try {
				if (!sc.Connect()) {
					err_message = "接続に失敗しました";
					bResult = false;
				}
				else {
					sc.SendMail(mw);
					sc.Close();
				}
			}
			catch (Exception ex) {
				err_message = ex.Message;
				bResult = false;
			}
			if (!bResult) {
				if (mce != null) {
					MailClassErrorArg e = new MailClassErrorArg() { Message = err_message };
					// このメソッドの引数である、ErrorHandler デリゲートを呼び出す
					mce(e);
				}
			}

			return bResult;
		}

		public bool SendMail(string To, string From, string Subject, string Body, string To_J, string From_J) {
			return SendMail(To, From, Subject, Body, To_J, From_J, null);
		}

		public bool SendMail(string To, string From, string Subject, string Body) {
			return SendMail(To, From, Subject, Body, null, null, null);
		}

	}

}

関連する記事

VS2010(C#) : TKMP.DLLを使った、メール送信テンプレート




posted by lightbox at 2018-01-23 21:23 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年12月19日


C# : Excel を データベースとして DataGridView に読み込む

※ Microsoft Office の Excel がインストールされている必要はありません

Microsoft.ACE.OLEDB.12.0 を使用して、OleDbConnection と OleDbCommand でデータベースとして処理します。テーブル名としては、シート名が使われますが、範囲指定して名前を定義しない限りは [シート名$] をテーブル
として使用します。( カギかっこは、Oracle で言うところのダブルクォートです )

Microsoft.ACE.OLEDB.12.0 がインストールされていない場合

Microsoft Access データベース エンジン 2010 再頒布可能コンポーネントをダウンロードしてインストールします。


( 32ビット版と64ビット版があるので選択してダウンロードします / ※ システム要件に 『32 ビット版の Access データベース エンジンは、Windows XP Service Pack 3 でしか使用できません』とあります。Windows7 では既にインストールされていると思われます )

▼ ダウンロードページの『インストール方法』より抜粋
OLEDB を使用するアプリケーション開発者: ConnectionString プロパティのプロバイダー引数を "Microsoft.ACE.OLEDB.12.0" に設定します。 

Microsoft Office Excel データに接続する場合は、Excel ファイル形式に基づいて OLEDB 接続文字列の適切な拡張プロパティを追加します 

ファイル形式 (拡張子)                                             拡張プロパティ
---------------------------------------------------------------------------------------------
Excel 97-2003 ブック (.xls)                                  "Excel 8.0"
Excel 2007-2010 ブック (.xlsx)                             "Excel 12.0 Xml"
Excel 2007-2010 マクロ有効ブック (.xlsm)      "Excel 12.0 Macro"
Excel 2007-2010 XML 以外のバイナリ ブック (.xlsb)      "Excel 12.0"
処理コード
	public partial class FormExcelGridView : Form {

		private string path = null;

		public FormExcelGridView() {
			InitializeComponent();
		}

		private void buttonExcel_Click(object sender, EventArgs e) {

			path = Helper.OpenFileDialog();
			if (path == null) {
				return;
			}

			LoadExcel();

		}

		// *********************
		// Excel の読み込み
		// *********************
		private void LoadExcel() {

			using (OleDbConnection myCon = new OleDbConnection())
			using (OleDbCommand myCommand = new OleDbCommand()) {

				// SQL文字列格納用
				string myQuery = "select * from [sheet1$]";

				// 接続文字列の作成
				myCon.ConnectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\"", path);
				Debug.WriteLine(myCon.ConnectionString);

				// *********************
				// 接続
				// *********************
				try {
					// 接続文字列を使用して接続
					myCon.Open();
					// コマンドオブジェクトに接続をセット
					myCommand.Connection = myCon;
					// コマンドを通常 SQL用に変更
					myCommand.CommandType = System.Data.CommandType.Text;
				}
				catch (Exception ex) {
					MessageBox.Show(this, ex.Message);
					return;
				}

				// *********************
				// 実行 SQL
				// *********************
				myCommand.CommandText = myQuery;

				// *********************
				// レコードセット取得
				// *********************
				try {
					using (OleDbDataReader myReader = myCommand.ExecuteReader()) {

						DataTable dataTable = new DataTable();
						dataTable.Load(myReader);
						dataGridView.DataSource = dataTable;

						// リーダを使い終わったので閉じる
						myReader.Close();
					}
				}
				catch (Exception ex) {
					myCon.Close();
					MessageBox.Show(this, ex.Message);
					return;
				}

				// 接続解除
				myCon.Close();

			}	// 最外の using の終わり

			// カラム幅の自動調整
			dataGridView.AutoResizeColumns();

		}
	}



Helpre クラス
	class Helper {

		// https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/application-object-excel
		public const int xlMaximized = -4137;
		public const int xlMinimized = -4140;
		public const int xlNormal = -4143;

		public static string OpenFileDialog() {

			OpenFileDialog ofd = new OpenFileDialog();

			ofd.Filter = "Excel(*.xls;*.xlsx;*.xlsm)|*.xls;*.xlsx;*.xlsm|すべてのファイル(*.*)|*.*";
			ofd.FilterIndex = 1;
			ofd.Title = "Excel ブックを選択してください";
			ofd.RestoreDirectory = true;

			if (ofd.ShowDialog() != DialogResult.OK) {
				return null;
			}

			return ofd.FileName;
		}
	}


DataGridView のプロパティ
            // 
            // dataGridView
            // 
            this.dataGridView.AllowUserToAddRows = false;
            this.dataGridView.AllowUserToDeleteRows = false;
            this.dataGridView.AllowUserToOrderColumns = true;
            this.dataGridView.AllowUserToResizeRows = false;
            this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView.Location = new System.Drawing.Point(40, 113);
            this.dataGridView.MultiSelect = false;
            this.dataGridView.Name = "dataGridView";
            this.dataGridView.ReadOnly = true;
            this.dataGridView.RowTemplate.Height = 21;
            this.dataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
            this.dataGridView.Size = new System.Drawing.Size(930, 443);
            this.dataGridView.TabIndex = 0;


関連する記事

C# : dynamic 型 による Excel へのアクセス



posted by lightbox at 2017-12-19 00:12 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年12月17日


C# : dynamic 型 による Excel へのアクセス

dynamic 型のオブジェクトは静的な型チェックをバイパスします。 なので、そのオブジェクトに対して熟練している必要がありますが、COM を使用する事を想定している場合、プログラマはそのメソッドに対して良く経験しているはすです。

▼ テンプレートのダウンロード


Excel の初期化部分と終了部分
		// *********************
		// 初期処理
		// *********************
		private void Form1_Load(object sender, EventArgs e) {

			excelApp = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
			excelApp.Visible = true;

		}

		// *********************
		// 終了処理
		// *********************
		private void Form1_FormClosed(object sender, FormClosedEventArgs e) {

			if (excelApp != null) {
				if (workBook != null) {
					// 保存した事にする
					workBook.Saved = true;
				}
				excelApp.Quit();
			}
			System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);

		}
Excel.Application は、VBScript では CreateObject で使用する ID です。excelApp は、dynamic 型で定義されており、excelApp.Visible = true; は、Excel が表示される事を意味します。



本来は、非表示でなければなりませんが(ユーザが直接操作するとエラーが発生します)、アプリケーション側(C#)が完成せずにテスト段階でエラーを起こしてしまうと、Excel が終了せずにメモリに残ってしまうので(その場合はタスクマネージャより終了させる)、このようにしています。

実装している機能

Excel には気の遠くなるほど、機能がたくさんあります。その中でも基本となる部分を実装しました。
1) セルへの書き込み。

2) Book を開いて、シート名の一覧をコンボボックスに表示

3) 各 シートをアクティブにする

4) Book を閉じる

5) Book を保存して閉じる

6) 最大化・最小化・標準表示
ソースコード
	public partial class Form1 : Form {

		private dynamic excelApp = null;
		private dynamic workBook = null;
		private string path = null;

		public Form1() {
			InitializeComponent();
		}

		// *********************
		// 書き込みテスト
		// *********************
		private void buttonTest_Click(object sender, EventArgs e) {

			if (workBook == null) {
				return;
			}

			// セル用変数
			dynamic cell;
			// 行と列より、セルオブジェクト(アクティブシート)
			cell = workBook.ActiveSheet.Cells(numericRow.Value, numericColumn.Value);
			// セルに値をセット
			cell.Value = textString.Text;

		}

		// *********************
		// アクティブにする
		// *********************
		private void buttonActive_Click(object sender, EventArgs e) {

			if (workBook == null) {
				return;
			}

			string sheetName = listBoxSheet.Text;
			workBook.Sheets(sheetName).Activate();

		}

		// *********************
		// 初期処理
		// *********************
		private void Form1_Load(object sender, EventArgs e) {

			excelApp = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
			excelApp.Visible = true;

		}

		// *********************
		// 終了処理
		// *********************
		private void Form1_FormClosed(object sender, FormClosedEventArgs e) {

			if (excelApp != null) {
				if (workBook != null) {
					// 保存した事にする
					workBook.Saved = true;
				}
				excelApp.Quit();
			}
			System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);

		}

		// *********************
		// ブックを開く
		// *********************
		private void 開く_Click(object sender, EventArgs e) {

			if (workBook != null) {
				MessageBox.Show(this, "ブックは一つしか開く事ができません");
				return;
			}

			path = Helper.OpenFileDialog();
			if (path != null) {
				workBook = excelApp.Workbooks.Open(path);
				listBoxSheet.Items.Clear();
				// シートの数によりループ
				for (int i = 1; i <= workBook.Sheets.Count; i++) {
					// シート名をコンボボックスにセット
					listBoxSheet.Items.Add(workBook.Sheets(i).Name);
				}
				// コンボボックスを使用可能にして
				listBoxSheet.Enabled = true;
				// 先頭を選択する
				listBoxSheet.SelectedIndex = 0;
			}

		}

		// *********************
		// 閉じる
		// *********************
		private void 閉じる_Click(object sender, EventArgs e) {

			if (workBook != null) {
				// 保存した事にする
				workBook.Saved = true;
			}
			workBook.Close();
			workBook = null;

			// クリア
			listBoxSheet.Items.Clear();
			// リストボックスを使用不可にして
			listBoxSheet.Enabled = false;
			// 選択しない
			listBoxSheet.SelectedIndex = -1;

		}

		// *********************
		// 保存して閉じる
		// *********************
		private void 保存して閉じる_Click(object sender, EventArgs e) {

			if (workBook != null) {
				workBook.Save();
			}
			workBook.Close();
			workBook = null;

			// クリア
			listBoxSheet.Items.Clear();
			// リストボックスを使用不可にして
			listBoxSheet.Enabled = false;
			// 選択しない
			listBoxSheet.SelectedIndex = -1;

		}

		// *********************
		// 最大化
		// *********************
		private void 最大化_Click(object sender, EventArgs e) {

			excelApp.WindowState = Helper.xlMaximized;

		}

		// *********************
		// 最小化
		// *********************
		private void 最小化_Click(object sender, EventArgs e) {

			excelApp.WindowState = Helper.xlMinimized;

		}

		// *********************
		// 標準
		// *********************
		private void 標準_Click(object sender, EventArgs e) {

			excelApp.WindowState = Helper.xlNormal;

		}


	}



Helpre クラス
	class Helper {

		// https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/application-object-excel
		public const int xlMaximized = -4137;
		public const int xlMinimized = -4140;
		public const int xlNormal = -4143;

		public static string OpenFileDialog() {

			OpenFileDialog ofd = new OpenFileDialog();

			ofd.Filter = "Excel(*.xls;*.xlsx;*.xlsm)|*.xls;*.xlsx;*.xlsm|すべてのファイル(*.*)|*.*";
			ofd.FilterIndex = 1;
			ofd.Title = "Excel ブックを選択してください";
			ofd.RestoreDirectory = true;

			if (ofd.ShowDialog() != DialogResult.OK) {
				return null;
			}

			return ofd.FileName;
		}
	}


関連する記事

C# : Excel を データベースとして DataGridView に読み込む



タグ:C# EXCEL
posted by lightbox at 2017-12-17 20:29 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2017年11月26日


C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (4)



C# でDXライブラリを使って簡単なシューティングをクラス化して標準化 / メインループとプレイヤー (3) で、Game、Player という二つのクラスで、左右の矢印キーでプレイヤーの画像が左右に動く処理を標準化しました。

この Player クラスの機能をそのまま使って、背景を表示する Background クラスを追加します。背景画像はこちらからダウンロードできますが、サイズは 1007x1007 という中途半端なサイズになっています。

この画像はパターン画像で、左端が右端に続き、上端が下端に続く画像で、適当に作ったのでこのようなサイズになっています。ただ、1007 の幅なので、ゲーム画面の幅はこれ以内でないとうまく動作しないので注意して下さい。

Background クラス

背景は、プレイヤーの動きと逆に動くようになっています。また、背景は常に画面いっぱいに表示されるので、DrawRectGraph で描画しています。左端と右端を同時に更新する必要があるのですが、パターン画像なので、二つのエリアに分けて描画します。(矢印キーをずっと押し続けると、プレイヤーは画面の端で止まりますが、背景はずっと横スクロールし続けます)

現在横の動きだけなので二つの DrawRectGraph を使用していますが、縦の動きを入れる場合はさらに二つの DrawRectGraph が必要になる予定です。
		// *******************
		// コンストラクタ
		// *******************
		public Background(Game game, string name, int offset) {

			this.game = game;

			// 画像の読み込み
			image = DX.LoadGraph(name);

			// 画像のサイズを取得
			int w, h;
			DX.GetGraphSize(image, out w, out h);
			graph_w = w;
			graph_h = h;

			// 背景の初期位置
			x = 0;
			y = 0;

			move_offset = offset;

		}

		public int image { get; set; }
		public int graph_w { get; set; }
		public int graph_h { get; set; }
		public int x { get; set; }
		public int y { get; set; }
		public int move_offset { get; set; }
		public Game game { get; set; }

		// *******************
		// 描画
		// *******************
		internal void draw() {

			DX.DrawRectGraph(0, 0, this.graph_w - this.x, this.y, this.x, this.graph_h - this.y, this.image, 0, 0);
			DX.DrawRectGraph(this.x, 0, 0, this.y, this.graph_w, this.graph_h - this.y, this.image, 0, 0);

		}

		// *******************
		// 左移動
		// *******************
		internal void left() {

			this.x -= this.move_offset;

			// 背景は一周する
			if (this.x < 0) {
				// 左へ消えた部分は、右から出て来る
				this.x = this.graph_w;
			}

		}

		// *******************
		// 右移動
		// *******************
		internal void right() {

			this.x += 5;

			// 背景は一周する
			if (this.x >= this.graph_w) {
				// 右へ消えた部分は、左から出て来る
				this.x = 0;
			}

	
		}
	}


Background クラスを追加したメイン処理( Program クラス内 ) は以下のようになります

Program 内の処理

処理としては逆向きのメソッドをそれぞれ配置しただけのものになっています
			// メインゲームインスタンス作成
			Game game = new Game(800, 600);

			// 初期化
			game.init();

			// 背景インスタンス作成
			Background background = new Background(game, "field.png", 5);

			// プレイヤーインスタンス作成
			Player player = new Player(game, "player.png", 5);

			game.start(
				// *******************
				// 主処理
				// *******************
				(int counter) => {

					// 右矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_RIGHT) == 1) {

						player.right();
						// player と 逆向き
						background.left();

					}

					// 左矢印キー
					if (DX.CheckHitKey(DX.KEY_INPUT_LEFT) == 1) {

						player.left();
						// player と 逆向き
						background.right();

					}

				},
				// *******************
				// 描画処理
				// *******************
				() => {

					background.draw();
					player.draw();

				}

			);



posted by lightbox at 2017-11-26 20:17 | VS(C#) | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり