11月 25

photo credit: ahisgett
Redmine Clientというアプリケーションがあります。Windows(.NET)上で動作するRedmineのクライアントで、機能的には、
- チケットに費やした時間を計測する
- 時間をRedmineへ登録する
- 新しいチケットを登録する
というシンプルなものです。C#で書かれています。
このアプリケーションにはRedmineへアクセスするためのライブラリ(DLL)が添付されており、APIの仕様も公開されています。(どちらかと言うと、アプリケーションはこのライブラリのサンプル的な位置付けなのかな?)
Redmineは0.9でRESTfulになるらしいので、それまで待とうか…という気もしないではないのですが、このライブラリのFUTURE PLANSには“Making use of Redmine 0.9 RESTfull interface”とあり、0.9でRESTfullになったら対応する模様。
ということで、安心して?試してみました。
インストールと設定
- ここからredmineclient-0.3.0.zipをダウンロードする。
- アーカイブを解凍しNohal.Redmine.dllをVisual Studioのプロジェクトで参照設定する。
これだけです。
チケット一覧を取得するための基本的な流れ
以下のような流れでチケット一覧を取得できます。簡単。
- Redmineオブジェクトの生成
- RedmineのURLを設定(Redmine.RedmineBaseUriプロパティ)
- Redmineへのログイン(Redmine.LogInメソッド)
- プロジェクト一覧の取得(Redmine.GetProjectsメソッド)
- プロジェクトIDを指定してチケット一覧の取得(Redmine.GetIssuesメソッド)
(載せるまでも無いですが)実際のコードはこんな感じ。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Nohal.Redmine;
namespace RedmineTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Redmine redmine = new Redmine();
redmine.RedmineBaseUri = "RedmineのURL";
redmine.LogIn("Redmineのユーザ名", "Redmineのパスワード");
List<Project> projects = redmine.GetProjects();
textBox1.Text = "プロジェクト一覧\r\n";
foreach (Project project in projects)
textBox1.Text += project.Id.ToString() + ": " + project.Name + "\r\n";
textBox1.Text += "チケット一覧\r\n";
// GetIssues(3)の3はプロジェクトID。本来はGetProjects()で取得したIDを指定する。
foreach (Issue issue in redmine.GetIssues(3))
textBox1.Text += issue.Id + ": " + issue.Subject + "\r\n";
}
}
}
ざっとAPI仕様を眺めた限りでは、条件を指定してチケットを絞り込む方法が無さそうです。
このため、指定したプロジェクトの全チケットがListで返却されますので、チケット数が数千~数万のオーダーになると厳しいかもしれませんが、チケットの登録はイケるでしょう。
C#から簡単にRedmineへアクセスできるのはいいですね。Redmineクライアントの開発をお考えての方はお試しください。
11月 23

photo credit: ArtBrom
MPXJというMicrosoft Projectのファイルへアクセスするためのライブラリを試してみました。MPXJは以下のファイル形式に対応しています。
- Microsoft Project Exchange (MPX)
- Microsoft Project (MPP,MPT)
- Microsoft Project Data Interchange (MSPDI XML)
- Microsoft Project Database (MPD),Planner (XML).
MPXJはJavaで書かれているのですがIKVMにより.NETからも使うことができます。
インストールと設定
- Browse MPXJ: Microsoft Project Exchange Files on SourceForge.netからmpxj-3.1.0.zipをダウンロードし、任意のディレクトリへ展開する。
- 展開後lib.netディレクトリにある以下のファイルをVisual Studioのプロジェクトから参照できるように設定する。
- IKVM.OpenJDK.ClassLibrary.dll
- IKVM.Runtime.dll
- mpxj.dll
- poi-3.2-FINAL-20081019.dll
- MPXJのクラスリファレンスはOverview (MPXJ API)を参照
これだけ。サンプルとしてこんなコードを書いてみました。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using net.sf.mpxj;
using net.sf.mpxj.reader;
using net.sf.mpxj.writer;
namespace MPXJTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
OpenProjectFile(openFileDialog1.FileName);
}
private void OpenProjectFile(string fileName)
{
ProjectReader reader = ProjectReaderUtility.getProjectReader(fileName);
ProjectFile projectFile = reader.read(fileName);
ProjectHeader projectHeader = projectFile.getProjectHeader();
textBox1.Text = "プロジェクト名: " + projectHeader.getProjectTitle();
textBox1.Text += "\r\nプロジェクト開始日: " + projectHeader.getStartDate();
textBox1.Text += "\r\nプロジェクト終了日: " + projectHeader.getFinishDate();
textBox1.Text += "\r\n担当者";
foreach (Resource resource in projectFile.getAllResources().toArray())
textBox1.Text += "\r\n" + resource.getID() + ": " + resource.getName();
textBox1.Text += "\r\nタスク";
foreach (Task task in projectFile.getAllTasks().toArray())
textBox1.Text += "\r\n" + GetTaskLevelIndent(task) + task.getName();
}
private string GetTaskLevelIndent(Task task)
{
string level = "";
while ((task = task.getParentTask()) != null)
level += "|--";
return level;
}
}
}
このコードは指定されたMicrosoft Projectのファイルからプロジェクト名、プロジェクト開始日、プロジェクト終了日、担当者一覧、タスク一覧をテキストボックスへ出力するものです。
マイクロソフトのWebサイトで提供しているベンダーに対する提案依頼書の要請 – テンプレート – Microsoft Office Onlineを読み込んだ結果はこちら。
プロジェクト名:
プロジェクト開始日: Mon Jan 01 08:00:00 GMT 2007
プロジェクト終了日: Thu Feb 01 12:00:00 GMT 2007
担当者
0:
1: 購買マネージャ
2: ユーザー チーム
3: 評価委員会
4: 意思決定グループ
タスク
ベンダーに対する提案依頼書 (RFP) の要請
|--このテンプレートの目的を説明するメモを読む
|--RFP の基準
|--|--RFP 作成の正式なプロセスが必要かどうかを判断する基準のレビュー
|--|--購買担当に RFP を作成する必要があることについて通知
|--RFP 要請プロセス
|--|--要求の定義
|--|--|--製品とサービスのニーズを理解するためにユーザーにインタビュー
|--|--|--要求の文書化
|--|--|--回答の評価基準の定義
|--|--|--評価チームの特定
|--|--RFP の作成
|--|--|--購買担当から RFP の書式のテンプレートを取得
|--|--|--RFP のドラフト作成
|--|--|--購買担当、該当分野の専門家と RFP をレビュー
|--|--|--RFP の改良
|--|--|--RFP の内容の準備完了
|--|--市場調査
|--|--|--該当する製品またはサービスを提供するベンダー候補企業の特定
|--|--|--事前の情報提供依頼書 (RFI) が必要かどうかを決定
|--|--|--RFI の回答の収集 (必要な場合)
|--|--|--RFP の対象企業の最終決定
|--|--業界への RFP の送付
|--|--|--特定の回答段階についての期限の決定
|--|--|--期限と連絡先を記載した RFP の完成
|--|--|--RFP を対象企業に送付
|--|--|--RFP についての説明会の実施 (必要な場合)
|--|--RFP 収集プロセスの完了
|--収集後のプロセス
|--|--"入札意思あり" の回答のまとめ
|--|--質問回答プロセス
|--|--|--入札企業からの質問のまとめ
|--|--|--質問に対する正式な回答の準備
|--|--|--'入札意思あり' と表明したすべての企業に回答を公開
|--|--提案書のレビュー
|--|--|--初期評価を実施して問題を明確化
|--|--|--設定した基準に基づいて提案書を評価
|--|--|--基準を満たしていない提案企業を除外
|--|--|--残りの提案企業との話し合いの準備
|--|--個別会議/交渉
|--|--|--最終選考に残った企業にソリューションのプレゼンテーションを依頼
|--|--|--最終選考に残った企業のソリューションとデモを分析
|--|--選択の決定
|--|--|--提案書の最終分析
|--|--|--ベンダーの選択
|--|--|--契約の締結
|--|--|--選ばれなかった提案企業からフィードバックを収集
|--|--収集後のフェーズの完了
|--ベンダーからの提案依頼書 (RFP) の収集の完了
必要な情報だけを抜いてCSV出力するようなプログラムは簡単に書けそうですね。
弊社のプロジェクト管理ソフトProjectscapeでMicrosoft Projectファイルインポート機能をサポートするのにも使えそうな感じが…もう少し評価してみたいと思います。
11月 07

Evernoteは開発者向けにAPIを提供しています。
C#で書こうとしているちょっとしたプログラムの調査のため、Evernote APIをラップするC#のライブラリEvernoteSharp試してみました。
Evernote APIを使うためには、API Keyを払い出してもらう必要があります。Request an API Keyから、必要事項を書いて申し込みます。私の場合は申し込んでから1時間半ぐらいでAPI Keyがメールで送られてきました。仕事が速いですね!
API Keyは開発用環境であるSandBoxのみで有効です。このため、普段使っているアカウントとは別にEvernote Registrationからテスト専用のアカウントを登録します。
次に、Visual StudioでWindowsアプリケーションのプロジェクトを作成します。EvernoteSharpをダウンロードし、アーカイブを解凍してEvernoteSharp.dllをプロジェクトの参照設定へ追加します。準備はこれで完了。
以下のコードは、指定した画像ファイルをEvernoteのデフォルトのノートブックへ追加するものです。
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using EvernoteSharp;
namespace EvernoteSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
StoreFactory sf = new StoreFactory(new Uri(&quot;http://sandbox.evernote.com/&quot;), &quot;your-api-key-here!&quot;, &quot;your-api-secret-here!&quot;);
UserStoreWrapper userStore = sf.CreateUserStore();
if (!userStore.CheckVersion())
throw new Exception(&quot;Invalid API version&quot;);
userStore.Authenticate(&quot;your-username&quot;, &quot;your-password&quot;);
NoteStoreWrapper noteStore = sf.CreateNoteStore();
Evernote.EDAM.Type.Data data = new Evernote.EDAM.Type.Data();
FileStream fs = new FileStream(tbTitle.Text, FileMode.Open, FileAccess.Read);
byte[] bImageFile = new byte[fs.Length];
fs.Read(bImageFile, 0, bImageFile.Length);
fs.Close();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] bs = md5.ComputeHash(bImageFile);
string hashHex = BitConverter.ToString(bs).ToLower().Replace(&quot;-&quot;,&quot;&quot;);
data.Size = bImageFile.Length;
data.BodyHash = bs;
data.Body = bImageFile;
Evernote.EDAM.Type.Resource resource = new Evernote.EDAM.Type.Resource();
resource.Mime= &quot;image/png&quot;;
resource.Data = data;
Evernote.EDAM.Type.Note note = new Evernote.EDAM.Type.Note();
var defaultNotebook = noteStore.GetDefaultNotebook();
note.NotebookGuid = defaultNotebook.Guid;
note.Title = tbTitle.Text;
note.Content = &quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot;?&gt;&quot; +
&quot;&lt;!DOCTYPE en-note SYSTEM \&quot;http://xml.evernote.com/pub/enml.dtd\&quot;&gt;&quot; +
&quot;&lt;en-note&gt;&quot; +
&quot;&lt;en-media type=\&quot;image/png\&quot; hash=\&quot;&quot; + hashHex + &quot;\&quot;/&gt;&quot; +
&quot;&lt;/en-note&gt;&quot;;
note.Updated = note.Created;
List&lt;Evernote.EDAM.Type.Resource&gt; resourceList = new List&lt;Evernote.EDAM.Type.Resource&gt;();
resourceList.Add(resource);
note.Resources = resourceList;
noteStore.CreateNote(note);
MessageBox.Show(tbTitle.Text + &quot;をEvernoteへ追加しました&quot;);
}
private void button2_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
tbTitle.Text = openFileDialog1.FileName;
}
}
}
うん、これでなんとかいけそう。
Evernote APIの資料はこちらです。