「ほっ」と。キャンペーン
タグ:.Net ( 213 ) タグの人気記事
(.Net)DataTableへのアクセスで列名で指定すると遅くなる
DataTableの特定の列にアクセするときの列の指定で、列名でアクセスすると、DataColumnやインデックスでアクセスするときに比べ2倍ほど遅くなるようです。
なので、列にアクセするときはなるべくインデックスかDataColumnを使いましょう。

同じように、ループ時に一旦新たに DataRow を作成し、そこに代入、そのDataRowから各列にアクセスとするか、foreach でのアクセスが望ましいようですね。
Rowsへのアクセスも全行舐めるような処理の時に DataTable.Rows[rowIndex][colIndex] とすると上の方法に比べ、4倍程度遅くなるようです。


.SelectメソッドにいたってはLinqやループで検索するときに比べ数十倍遅いようです。データ量が多い時は Select メソッドは使い物にならないかもしれません。

また、DataTableの書き込みに関しても BeginEdit,EndEditの無い場合、有る場合と比較して十数倍ほど遅くなります。BeginEdit,EndEditは使ったほうがよさそうです。

DataTableは便利だけど遅いので、結局クラス化してそれをListコレクションにしたほうがいいのかもしれません。

参考:
[.NET][C#]当然っちゃ当然だけどDataTableとか使いようによっては遅い
[.NET][C#]当然っちゃ当然だけどDataTableとか使いようによっては遅い その2
意外と遅い DataTable 、なので List を使うと 5 倍早くなる | Moonmile Solutions Blog
[PR]
by Jehoshaphat | 2012-05-12 12:30 | .Net開発 | Trackback | Comments(0)
(WindowsServer2008R2)GACに.Netアセンブリを登録したいがassemblyフォルダへのドラッグで拒否られる
WindowsServer2008 R2 のサーバで、.Net のアセンブリをGACに、C:\Windows\assembly フォルダへのドラッグアンドドロップで登録したかったんですが、結構ハマリました。
(エクスプローラからのGACからのアンインストールも同様だと思います。)

原因はUACです。まぁUAC切ればいいんですが、本番稼働中のRDSサーバのためそうはいきません。

Administratorsグループのユーザで、普通にドラッグアンドドロップすると下記のように怒られます。

アセンブリキャッシュビューア - インストールできませんでした。
アクセスが拒否されました。


Windowsエクスプローラ(explorer.exe)を右クリック→"管理者として実行"からやっても同様です。

explorer.exeのショートカットを作成し、互換性タブから管理者権限をつけようとしましたが、グレーアウトしてできません。
エクスプローラはOSの一機能なので互換性タブは使えないようです。

結局下記の方法で出来ました。


1.
まず、フォルダオプションで、"別のプロセスでフォルダーウィンドウを開く" のチェックが外れいていることを確認します。

2.
タスクマネージャーを起動し、explorer.exeを殺します。

3.
タスクマネージャーの "新しいタスク" で、C:\Windows\explorer.exe を 右クリック→"管理者として実行" します。

これで、アセンブリをドラッグアンドドロップすればGACに登録できました。


多分、Windows7やVistaでも同様だと思います。
いやぁー、結構面倒です。。。
[PR]
by Jehoshaphat | 2012-01-10 23:36 | .Net開発 | Trackback | Comments(0)
VisualStudio無いけど、.Net Framework1.1のアプリを作りたい
検証で、.Net Framework1.1の HelloWorld アプリケーションを作る必要がありました。

しかし、.Net Framewrok1.1用のIDEである VisutalStudio2003 が有りません。

ということで、IDEを使わずにコンパイルしてみました。

コンパイルには、.NetFramework1.1 SDKが必要です。

インストールして、下記のようなコードを書き、C:\helloroworld.cs に保存しました。

namespace helloworld
{
using System;
using System.Text;
using System.Windows.Forms;
class helloworld
{
public static void Main()
{
//ビルドCLRバージョン取得
string clrVerBuild = System.Reflection.Assembly.GetExecutingAssembly().ImageRuntimeVersion;
clrVerBuild = "ビルドCLR ver:" + clrVerBuild + "\n";
//実行CLRバージョン取得
string clrVerRuntime = System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion();
clrVerRuntime = "実行CLR ver:" + clrVerRuntime ;
MessageBox.Show( clrVerBuild + clrVerRuntime);
}
}
}


ビルドはコマンドプロンプトから、下記のようにしてやります。

C:\>C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\csc.exe C:\helloroworld.cs
Microsoft(R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft(R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


これで、カレントフォルダにexeが出来ていはずです。
簡単ですね。

参考:
.NET Framework 開発環境構築
[PR]
by Jehoshaphat | 2011-12-18 23:43 | .Net開発 | Trackback | Comments(0)
(.Net)ビルドされた時と実行時のFramework CLRのバージョンを知りたい
最近知ったんですが、例えば .Net Framework1.0 でアプリケーションを作成して、実行環境に .Net Framework2.0 しか入ってない場合、アプリケーションは2.0上のCLR(Common Language Runtime)で動こうとします。(基本的には、ビルドされた時と同じバージョンのCLRで動こうとします。)

ということで、ビルド時と実行時のCLRのバージョンを取得するアプリケーションをつくって試してみました。

まずビルド時のCLRのバージョンは下記のように取得できます。(C#)

//ビルドCLRバージョン取得(.NetFramework1.0では使用不可)
string clrVerBuild = System.Reflection.Assembly.GetExecutingAssembly().ImageRuntimeVersion;
label1.Text = "ビルドCLR ver:" + clrVerBuild;


実行時のCLRのバージョンは下記のように取得できます。

//実行CLRバージョン取得
string clrVerRuntime = System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion();
label2.Text = "実行CLR ver:" + clrVerRuntime;
 
//下記のようにしても取得できる(リビジョン番号も取得できるのでSP適用有無がわかる)
clrVerRuntime = System.Environment.Version.ToString();



余談ですが、.NetFrameworkの混在した環境でアプリケーションを動かすと、使用するCLRのバージョンは下記のようになります。
(もしかしたら間違いがあるかもしれませんが。。。また、.Net3.0/3.5部分はCLR2.0だけの機能を利用した場合です)
e0091163_23401234.jpg




CRLは現在、1.0 , 1.1 , 2.0 , 4.0 の4種類有ります。(.Net3.5 , 3.0 は .Net2.0 の拡張なので CLR は2.0になります)
.Net4 は下位互換性が全く無いようです。

.Netのサイドバイサイドを使えばアプリケーションが利用するCLRのバージョンを指定することもできるようです。

しかし、.Net Frameworkはアプリ作るときは楽なんですが、運用となるとこのあたりの事を考えないといけないので面倒ですね。


Windows7とWindowServer2008での.NetFramework1.0/1.1
最近まで知らなかったんですが、.Net Framework1.0 と 1.1 は Widnows7,WindowsServer2008 R2 ではサポートされなくなったようです。
これは .Net Framework1.0/1.1 を使ってるユーザには、非常に大きな問題ですよね。

しかし、.Net Framework1.0/1.1 のアプリケーションがWindows7,2008上で全く動かなくなる というわけではなく、冒頭のようにCLR2.0の下位互換性機能によって動くようです。
ただ、完全互換ではないので複雑なアプリケーションだとうまく動かないようですね。
業務アプリケーションで試してみましたが、下位互換性機能では動きませんでした。



参考:
@IT:.NET TIPS ビルド時および実行時のCLRバージョンを取得するには? - C# VB.NET
.NET Frameworkのバージョンを整理する - @IT
Windows Vistaにおける.NETアプリケーションの互換性問題 - Windows Vista徹底解説:ITpro
.NETFrameworkEnvironment - attosoft.info Trac
.NET Framework - Wikipedia
@IT:.NET TIPS サイド・バイ・サイドによりCLRバージョンを指定するには?
MSDN:side-by-side 実行の概要
.NET Framework 1.0/1.1 上で稼働するアプリケーションをお使いのお客様へ - .NET Framework 移行センター
[PR]
by Jehoshaphat | 2011-12-18 23:41 | .Net開発 | Trackback | Comments(0)
.NetからOpenOfficeCalcへの操作を汎用化したDLL(Part3)
.NetからOpenOfficeCalcへの操作を汎用化したDLL(Part2)の続きで、Part3です。(C#)



#region 各プロパティ設定デリゲートメソッド
/// <summary>文字色を設定する。(デリゲート経由で呼び出される) </summary>
/// <param name="prm"></param>
private void SetCharColorDelegate(PropertiesDelegateParam prm)
prm.XPropertySet.setPropertyValue("CharColor", new uno.Any(ConvertOooColorFromDotNetColor(prm.ColorValue)));
}
/// <summary>セル背景色を設定する。(デリゲート経由で呼び出される) </summary>
/// <param name="prm"></param>
private void SetCellBackColorDelegate(PropertiesDelegateParam prm) {
//下記の形式だとNGみたい
//prm.XPropertySet.setPropertyValue("CellBackColor", new uno.Any(ColorTranslator.ToWin32(prm.ColorValue)));
prm.XPropertySet.setPropertyValue("CellBackColor", new uno.Any(ConvertOooColorFromDotNetColor(prm.ColorValue)));
}
/// <summary> セル文字の大きさを設定する。(デリゲート経由で呼び出される</summary>)
/// <param name="prm"></param>
private void SetCharHeightDelegate(PropertiesDelegateParam prm) {
prm.XPropertySet.setPropertyValue("CharHeight", new uno.Any(prm.FloatValue ));
}
/// <summary> セル枠までのスペースを設定する。(デリゲート経由で呼び出される)</summary>
/// <param name="prm"></param>
private void SetParagraphDelegate(PropertiesDelegateParam prm) {
prm.XPropertySet.setPropertyValue(GetParagraphName(prm.SideValue), new uno.Any(prm.IntValue));
}
/// <summary>背景色を透過設定する。(デリゲート経由で呼び出される)</summary>
/// <param name="prm"></param>
private void SetIsCellBackgroundTransparentDelegate(PropertiesDelegateParam prm) {
prm.XPropertySet.setPropertyValue("IsCellBackgroundTransparent", new uno.Any(prm.BoolValue));
}

/// <summary>文字色を取得する。(デリゲート経由で呼び出される)</summary>
/// <param name="prm"></param>
private void GetCharColorDelegate(PropertiesDelegateParam prm) {
prm.ColorValue = Color.FromArgb((int)(prm.XPropertySet.getPropertyValue("CharColor").Value));
}
/// <summary> セル背景色を取得する。(デリゲート経由で呼び出される) </summary>
/// <param name="prm"></param>
private void GetCellBackColorDelegate(PropertiesDelegateParam prm) {
//下記の形式だとNGみたい
//prm.ColorValue = ColorTranslator.FromWin32((int)(prm.XPropertySet.getPropertyValue("CellBackColor").Value));
//prm.ColorValue = Color.FromArgb((int)(prm.XPropertySet.getPropertyValue("CellBackColor").Value));
prm.ColorValue = ConvertDotNetColorFromOooColor((int)(prm.XPropertySet.getPropertyValue("CellBackColor").Value));
}
/// <summary> セル文字の大きさを取得する。(デリゲート経由で呼び出される)</summary>
/// <param name="prm"></param>
private void GetCharHeightDelegate(PropertiesDelegateParam prm){
prm.FloatValue = (float)(prm.XPropertySet.getPropertyValue("CharHeight").Value);
}
/// <summary>セル枠までのスペースを取得する。(デリゲート経由で呼び出される)</summary>
/// <param name="prm"></param>
private void GetParagraphDelegate(PropertiesDelegateParam prm){
prm.IntValue = (int)(prm.XPropertySet.getPropertyValue(GetParagraphName(prm.SideValue)).Value);
}
/// <summary> 背景色を透過設定を取得する。(デリゲート経由で呼び出される)</summary>
/// <param name="prm"></param>
private void GetIsCellBackgroundTransparentDelegate(PropertiesDelegateParam prm){
prm.BoolValue = (bool)(prm.XPropertySet.getPropertyValue("IsCellBackgroundTransparent").Value);
}

/// <summary>パディング名を取得 </summary>
/// <param name="side"></param>
/// <returns></returns>
private string GetParagraphName(ParagraphSide side){
string strPropName = "";
switch (side) {
case ParagraphSide.Left:
strPropName = "ParaLeftMargin";
break;
case ParagraphSide.Right:
strPropName = "ParaRighttMargin";
break;
case ParagraphSide.Top:
strPropName = "ParaTopMargin";
break;
case ParagraphSide.Bottom:
strPropName = "ParaBottomMargin";
break;
default:
break;
}
return strPropName;
}

/// <summary> カラー情報をOpenOfficeで扱える形式に変換</summary>
private int ConvertOooColorFromDotNetColor(Color color) {
return (int)((int)color.R * Math.Pow(2, 16)
+ (int)color.G * Math.Pow(2, 8)
+ (int)color.B);
}
/// <summary>OpenOfficeのカラー情報を.Netの Color に変換</summary>
private Color ConvertDotNetColorFromOooColor(int iClr)
{
if (iClr < 0)
return Color.Transparent;//-1時は透明とみなす
return Color.FromArgb(iClr >> 16 , (iClr >> 8) & 0xFF, iClr & 0xFF );
}
#endregion

/// <summary> シートが選択されていないなら例外発生 </summary>
private void IsSheetNullCheckException(){
if (!IsSheetNullCheck()){
throw new OpenOfficeException("OpenOffice操作クラス例外:sheetが選択されていません。");
}
}
/// <summary>セルが選択されていないなら例外発生 </summary>
private void IsCellNullCheckException(){
if (!IsCellNullCheck()){
throw new OpenOfficeException("OpenOffice操作クラス例外:cellが選択されていません。");
}
}

#region IDisposable メンバ
/// <summary>クラス破棄時</summary>
public void Dispose(){
//OpenOffice閉じる
OpenOfficeClose();
//OpenOfficeのプロセス強制終了
OpenOfficeProcessKill();
}
#endregion
}

/// <summary>プロパティ設定・取得のための値を持つクラス。
/// Actionデリゲートでつかうるようにするため各型のを扱えるようにラップしたもの。 </summary>
class PropertiesDelegateParam{
private XPropertySet xPropSet;
private Color clrValue;
private double dValue;
private float fValue;
private int iValue;
private long lValue;
private string strValue;
private bool blValue;
private OpenOffice.ParagraphSide sideValue;
/// <summary>コンストラクタ。</summary>
/// <param name="xPropertySet">(XPropertySet)this.cell</param>
protected internal PropertiesDelegateParam(XPropertySet xPropertySet){
xPropSet = xPropertySet;
}
/// <summary>プロパティでカラー情報を設定・取得</summary>
protected internal Color ColorValue{
get { return clrValue; }
set { clrValue = value; }
}
/// <summary>プロパティで倍精度小数点を設定・取得</summary>
protected internal double DoubleValue{
get { return dValue; }
set { dValue = value; }
}
/// <summary>プロパティで単精度小数点を設定・取得</summary>
protected internal float FloatValue{
get { return fValue; }
set { fValue = value; }
}
/// <summary>プロパティで整数を設定・取得</summary>
protected internal int IntValue{
get { return iValue; }
set { iValue = value; }
}
/// <summary> プロパティで長整数を設定・取得 </summary>
protected internal long LongValue{
get { return lValue; }
set { lValue = value; }
}
/// <summary>プロパティで文字列を設定・取得</summary>
protected internal string StringValue{
get { return strValue; }
set { strValue = value; }
}
/// <summary>プロパティで真偽を設定・取得</summary>
protected internal bool BoolValue{
get { return blValue; }
set { blValue = value; }
}
/// <summary>プロパティで方向を設定・取得</summary>
protected internal OpenOffice.ParagraphSide SideValue{
get { return sideValue; }
set { sideValue = value; }
}
/// <summary>XPropertySetオブジェクトを取得</summary>
protected internal XPropertySet XPropertySet{
get { return xPropSet; }
}
}

/// <summary>このクラスの例外</summary>
class OpenOfficeException : System.Exception{
public OpenOfficeException(string message)
: base(message){
}
}
}

[PR]
by Jehoshaphat | 2011-10-20 02:29 | .Net開発 | Trackback | Comments(0)
NetからOpenOfficeCalcへの操作を汎用化したDLL(Part2)
.NetからOpenOfficeCalcへの操作を汎用化したDLL(Part1)の続きで、Part2です。(C#)



/// <summary>セル背景色を取得(先にSelectCellでセル指定が必要)</summary>
/// <returns>取得した文字色</returns>
public Color GetCellBackColorr() {
Action<PropertiesDelegateParam> getPropParam = GetCellBackColorDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
GetCoreProperties(getPropParam, prm);
return prm.ColorValue;
}
/// <summary>文字サイズを設定(先にSelectCellでセル指定が必要) </summary>
/// <param name="fSize">設定するサイズ</param>
public void SetCharHeight(float fSize) {
Action<PropertiesDelegateParam> setPropParam = SetCharHeightDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
prm.FloatValue = fSize;
SetCoreProperties(setPropParam, prm);
}
/// <summary> 文字サイズを取得(先にSelectCellでセル指定が必要)</summary>
/// <returns>取得した文字サイズ</returns>
public float GetCharHeight() {
Action<PropertiesDelegateParam> getPropParam = GetCharHeightDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
GetCoreProperties(getPropParam, prm);
return prm.FloatValue;
}
/// <summary>パディングサイズを設定(先にSelectCellでセル指定が必要) </summary>
public void SetParagraph(int iValue,ParagraphSide side) {
Action<PropertiesDelegateParam> setPropParam = SetCharHeightDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
prm.SideValue = side;
SetCoreProperties(setPropParam, prm);
}
/// <summary>パディングサイズを取得(先にSelectCellでセル指定が必要) </summary>
public int GetParagraph(ParagraphSide side) {
Action<PropertiesDelegateParam> getPropParam = GetParagraphDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
prm.SideValue = side;
GetCoreProperties(getPropParam, prm);
return prm.IntValue;
}
/// <summary> 背景色を透過設定(先にSelectCellでセル指定が必要) </summary>
public void SetIsCellBackgroundTransparent(bool bTrans){
Action<PropertiesDelegateParam> setPropParam = SetIsCellBackgroundTransparentDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
prm.BoolValue = bTrans;
SetCoreProperties(setPropParam, prm);
}
/// <summary>文字サイズを取得(先にSelectCellでセル指定が必要)</summary>
/// <returns>取得した文字サイズ</returns>
public bool GetIsCellBackgroundTransparent() {
Action<PropertiesDelegateParam> getPropParam = GetIsCellBackgroundTransparentDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
GetCoreProperties(getPropParam, prm);
return prm.BoolValue;
}

/// <summary> 行を挿入する</summary>
/// <param name="startRow">挿入開始行インデックス</param>
/// <param name="endRow">挿入する行の数</param>
public void InsertRowByIndex(int startRow, int insertRowsCount){
XColumnRowRange xCRRange = (XColumnRowRange)sheet;
XTableRows xRows = xCRRange.getRows();
xRows.insertByIndex(startRow, insertRowsCount);
}
/// <summary>指定した行を削除する </summary>
/// <param name="startRow">削除開始行インデックス</param>
/// <param name="endRos">削除する行の数</param>
public void RemoveRowByIndex(int startRow, int removeRowsCount){
XColumnRowRange xCRRange = (XColumnRowRange)sheet;
XTableRows xRows = xCRRange.getRows();
xRows.removeByIndex(startRow, removeRowsCount);
}

/// <summary> OpenOfficeのファイルを保存 </summary>
public void OpenOfficeSave() {
try{
//保存するために使うクラス(インターフェイス?)取得
XStorable xstorable = (XStorable)doc;
//保存時のプロパティ設定
PropertyValue[] storeProps = new PropertyValue[1];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "Overwrite"; //上書き
storeProps[0].Value = new uno.Any((Boolean)true);
String sURL = strUriFilePath;
//保存
xstorable.storeAsURL(sURL, storeProps);
}catch (System.Exception ex){
OpenOfficeProcessKill();
throw;
}
}

/// <summary>OpenOfficeのファイルを上書保存し、閉じる(プロセスも殺す) </summary>
public void OpenOfficeSaveAndClose(){
//保存するために使うクラス(インターフェイス?)取得
XStorable xstorable = (XStorable)doc;
//保存時のプロパティ設定
PropertyValue[] storeProps = new PropertyValue[1];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "Overwrite"; //上書き
storeProps[0].Value = new uno.Any((Boolean)true);
try{
String sURL = strUriFilePath;
//保存
xstorable.storeAsURL(sURL, storeProps);
//閉じる
OpenOfficeClose();
}catch (unoidl.com.sun.star.uno.Exception ex){
throw;
}finally{
//OpenOfficeのプロセス強制終了
OpenOfficeProcessKill();
}
}

/// <summary>OpenOfficeを閉じる(プロセスは殺さない) </summary>
public void OpenOfficeClose(){
if (doc != null){
XCloseable xCloseable = (XCloseable)doc;
xCloseable.close(true);
doc = null;
factory = null;
loader = null;
context = null;
}
}

/// <summary> OpenOfficeのプロセス強制終了をする。 </summary>
public static void OpenOfficeProcessKill() {
try{
//現在のユーザ名取得
string strUserName = Environment.UserName;
//open office のプロセス検索。
Process[] ps = Process.GetProcessesByName("soffice.bin");
//WMIからOpenOfficeのプロセス取得
ManagementObjectSearcher query = new ManagementObjectSearcher(@"SELECT * FROM Win32_Process Where Name = 'soffice.bin'");
ManagementObjectCollection col = query.Get();
//配列から1つずつ取り出す
foreach (System.Diagnostics.Process p in ps){
//現在のユーザ名とプロセスの実行ユーザ名が同じなら殺す
foreach (ManagementObject o in col){
int pId = int.Parse(o["ProcessId"].ToString());
Object[] UserInfo = new object[2];
o.InvokeMethod("GetOwner", UserInfo);
if (p.Id == pId && strUserName.Equals((string)UserInfo[0])){
p.Kill();
break;
}
}
}
} catch {
//プロセス強制終了時のエラーは無視
}
}

/// <summary>シートが選択されているかどうか</summary>
/// <returns></returns>
public bool IsSheetNullCheck(){
return (this.sheet == null ? false: true);
}
/// <summary> セルが選択されているかどうか</summary>
/// <returns></returns>
public bool IsCellNullCheck(){
return (this.cell == null ? false : true);
}

#region 汎用メソッド
/// <summary> プロパティをセットする汎用メソッド(共通部分のみ記述。実際の処理はデリゲートに任せる) </summary>
/// <param name="setPropParam">デリゲート変数</param>
/// <param name="prm">プロパティに設定する値クラス(各型を持っただけのエンティティクラス)</param>
private void SetCoreProperties(Action<PropertiesDelegateParam> setPropParam, PropertiesDelegateParam prm){
try {
IsSheetNullCheckException();
IsCellNullCheckException();
//デリゲート呼び出し
setPropParam(prm);
} catch (System.Exception ex) {
OpenOfficeProcessKill();
throw;
}
}
/// <summary> プロパティを取得する汎用メソッド(共通部分のみ記述。実際の処理はデリゲートに任せる) </summary>
/// <param name="getPropParam">デリゲート変数</param>
/// <param name="prm">プロパティに取得値をもつ値クラス(各型を持っただけのエンティティクラス)</param>
private void GetCoreProperties(Action<PropertiesDelegateParam> getPropParam, PropertiesDelegateParam prm){
try{
IsSheetNullCheckException();
IsCellNullCheckException();
//デリゲート呼び出し
getPropParam(prm);
}catch (System.Exception ex){
OpenOfficeProcessKill();
throw;
}
}
#endregion


続きは、.NetからOpenOfficeCalcへの操作を汎用化したDLL(Part3)へ。
[PR]
by Jehoshaphat | 2011-10-20 02:27 | .Net開発 | Trackback | Comments(0)
NetからOpenOfficeCalcへの操作を汎用化したDLL(Part1)
.NetからOpenOfficeCalcへの操作を汎用化したDLLのPart1です。(C#)



using System;
using System.Collections.Generic;
using System.Text;
using uno.util;
using unoidl.com.sun.star.frame;
using unoidl.com.sun.star.lang;
using unoidl.com.sun.star.sheet;
using unoidl.com.sun.star.table;
using unoidl.com.sun.star.uno;
using unoidl.com.sun.star.beans;
using unoidl.com.sun.star.util;
using unoidl.com.sun.star.text;
using System.Management;
using System.Diagnostics;
using unoidl.com.sun.star.container;
using System.Drawing;
namespace OpenOfficeAccessRapper{
public class OpenOfficeRapper : IDisposable{
private XComponentContext context;
private XMultiServiceFactory factory;
private XComponentLoader loader;
private XSpreadsheetDocument doc;
private XSpreadsheets sheets;
private XSpreadsheet sheet;
private XCell cell;
private XCellRange xCellRange;
private string strUriFilePath;
public XCell Cell{
get { return cell; }
}
/// <summary>各方向を表す列挙型</summary>
public enum ParagraphSide{
Left, Right, Top, Bottom
}

/// <summary>コンストラクタ</summary>
/// <param name="calcFileName">Calcのファイル名</param>
public OpenOffice( string calcFileName ) {
//ファイルパスを変換
Uri uriCalcFile;
Uri.TryCreate(calcFileName, UriKind.Absolute, out uriCalcFile);
strUriFilePath = uriCalcFile.ToString();
//コンポーネントコンテキストオブジェクト取得(OpenOfficeの基本プロセスらしい)
context = Bootstrap.bootstrap();
//サービスマネージャ取得
factory = (XMultiServiceFactory)context.getServiceManager();
//コンポーネントローダオブジェクト取得
loader = (XComponentLoader)factory.createInstance("com.sun.star.frame.Desktop");
//非表示で実行するためのプロパティ指定
PropertyValue[] args1 = new PropertyValue[1];
args1[0] = new PropertyValue();
args1[0].Name = "Hidden";
args1[0].Value = new uno.Any((Boolean)true);
//ファイルを開きドキュメントオブジェクトを生成
doc = (XSpreadsheetDocument)loader.loadComponentFromURL(strUriFilePath, "_blank", 0, args1);// null);
//シートたちを取得
sheets = doc.getSheets();
}

/// <summary>シートを選択する(選択したシートはメンバ変数に保持) </summary>
/// <param name="sheetName">シート名</param>
public void SelectSheet(string sheetName) {
try {
this.sheet = (XSpreadsheet)this.sheets.getByName(sheetName).Value;
} catch (System.Exception ex) {
OpenOfficeProcessKill();
throw;
}
}

/// <summary> 現在アクティブなシートで指定したセルを選択。選択したセルはメンバ変数に持つ。</summary>
public void SelectCell(int iColumn, int iRow) {
try {
IsSheetNullCheckException();
this.cell = this.sheet.getCellByPosition(iColumn, iRow);
} catch (System.Exception ex) {
OpenOfficeProcessKill();
throw;
}
}

/// <summary>指定されたセル範囲を選択(選択したセル範囲はメンバ変数に保持)</summary>
public void SelectRangeByPosition(int nLeft, int nTop, int nRight, int nBottom){
try {
IsSheetNullCheckException();
xCellRange = sheet.getCellRangeByPosition(nLeft, nTop, nRight, nBottom);
} catch (System.Exception ex) {
OpenOfficeProcessKill();
throw;
}
}

/// <summary>選択したセル範囲に罫線を引く(先にSelectRangeByPositionでセル範囲指定が必要) </summary>
public void Border(int color) {
XPropertySet xPropSet = (XPropertySet)xCellRange;
BorderLine aLine = new BorderLine();
aLine.Color = color;
aLine.InnerLineWidth = aLine.LineDistance = 0;
aLine.OuterLineWidth = 10;
TableBorder aBorder = new TableBorder();
aBorder.TopLine = aBorder.BottomLine = aBorder.LeftLine = aBorder.RightLine = aLine;
aBorder.IsTopLineValid = aBorder.IsBottomLineValid = true;
aBorder.IsLeftLineValid = aBorder.IsRightLineValid = true;
aBorder.IsVerticalLineValid = true;
aBorder.IsHorizontalLineValid = true;
aBorder.HorizontalLine = aBorder.VerticalLine = aLine;
xPropSet.setPropertyValue("TableBorder", new uno.Any(typeof(unoidl.com.sun.star.table.TableBorder), aBorder));
}

/// <summary>現在選択しているセルに数値を代入(先にSelectCellでセル指定が必要) </summary>
public void SetCellValue(double value) {
try {
IsSheetNullCheckException();
IsCellNullCheckException();
this.cell.setValue(value);
} catch (System.Exception ex) {
OpenOfficeProcessKill();
throw;
}
}

/// <summary>現在選択しているセルの数値を取得(先にSelectCellでセル指定が必要)</summary>
public double GetCellValue() {
double d ;
try {
IsSheetNullCheckException();
IsCellNullCheckException();
d = this.cell.getValue();
}catch (System.Exception ex) {
OpenOfficeProcessKill();
throw;
}
return this.cell.getValue();
}

/// <summary>現在選択しているセルに数式を代入(先にSelectCellでセル指定が必要)</summary>
public void SetCellFormula(string value) {
try{
IsSheetNullCheckException();
IsCellNullCheckException();
this.cell.setFormula(value);
}catch (System.Exception ex) {
OpenOfficeProcessKill();
throw;
}
}

/// <summary>現在選択しているセルの数式を取得(先にSelectCellでセル指定が必要) </summary>
public string GetCellFormula(){
string str = string.Empty;
try{
IsSheetNullCheckException();
IsCellNullCheckException();
str=this.cell.getFormula();
}catch (System.Exception ex){
OpenOfficeProcessKill();
throw;
}
return str;
}


/// <summary> 現在選択しているセルの文字列を取得(先にSelectCellでセル指定が必要)</summary>
public string GetCellString() {
string str = string.Empty;
try {
IsSheetNullCheckException();
IsCellNullCheckException();
XText txt = (XText)this.cell;
str = txt.getString();
}catch (System.Exception ex){
OpenOfficeProcessKill();
throw;
}
return str;
}

/// <summary>セル文字色を設定(先にSelectCellでセル指定が必要) </summary>
/// <param name="CharColor">設定するカラー構造体</param>
public void SetCharColor(Color CharColor) {
Action<PropertiesDelegateParam> setPropParam = SetCharColorDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
prm.ColorValue = CharColor;
SetCoreProperties(setPropParam,prm);
}
/// <summary>セル文字色を取得(先にSelectCellでセル指定が必要) </summary>
/// <returns>取得した文字色</returns>
public Color GetCharColor() {
Action<PropertiesDelegateParam> getPropParam = GetCharColorDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
GetCoreProperties(getPropParam, prm);
return prm.ColorValue;
}
/// <summary> セル背景色を設定(先にSelectCellでセル指定が必要)</summary>
/// <param name="CharColor">設定するカラー構造体</param>
public void SetCellBackColor(Color CharColor){
Action<PropertiesDelegateParam> setPropParam = SetCellBackColorDelegate;
PropertiesDelegateParam prm = new PropertiesDelegateParam((XPropertySet)this.cell);
prm.ColorValue = CharColor;
SetCoreProperties(setPropParam, prm);
}



続きは、.NetからOpenOfficeCalcへの操作を汎用化したDLL(Part2)へ。
[PR]
by Jehoshaphat | 2011-10-20 02:23 | .Net開発 | Trackback | Comments(0)
(.Net,OpenOffice).NetからCalc操作時にセルのプロパティを変更する
.NetからOpenOfficeのCalcを操作する基本の方法は、(.Net,OpenOffice).NetからCalc操作時に罫線(枠線)を引くが参考になります。

今回は、セルの文字色、背景色、文字の大きさ、セル枠までのスペース(パディング)を変更する方法です。

サンプルは、OpenOffice.org_3.2_SDK\sdk\examples\CLI\CSharp\Spreadsheet\SpreadsheetDocHelper.cs の prepareRange メソッドに書いてあります。
サンプルでは下記のようになっています。

// --- Change cell properties. ---
xPropSet = (unoidl.com.sun.star.beans.XPropertySet) xCell;
// from styles.CharacterProperties
xPropSet.setPropertyValue(
"CharColor", new uno.Any( (Int32) 0x003399 ) );
xPropSet.setPropertyValue(
"CharHeight", new uno.Any( (Single) 20.0 ) );
// from styles.ParagraphProperties
xPropSet.setPropertyValue(
"ParaLeftMargin", new uno.Any( (Int32) 500 ) );
// from table.CellProperties
xPropSet.setPropertyValue(
"IsCellBackgroundTransparent", new uno.Any( false ) );
xPropSet.setPropertyValue(
"CellBackColor", new uno.Any( (Int32) 0x99CCFF ) );


ハマったのは色の設定です。
.Net の Color構造体をそのまま使おうとしたのですが、アルファ値を含むので使えません。
ColorTranslator.ToWin32 メソッドを使ってアルファ値を含まないInt32型の値を使おうとしましたが、どうも違う色になってしまいます。
ColorTranslator.ToWin32 メソッドの返り値で表すカラー情報はCOLORREF型という4バイトの符合なし整数のようで、内部的には 0x00BBGGRR で色を表しているようです。
OpenOfficeのプロパティに設定すべきなのは 0xRRGGBB になるので、違う色になってしまうのですね。

結局色に関して、Color構造体を 0xRRGGBB に変換するときは Rに2^16したもの + Gに2^8したもの + B としました。
逆に 0xRRGGBB から Color構造体を作るときは、Rは16ビット右シフト,Gは8ビット右シフト,Bはそのまま の値で Color.FromArgb メソッドから生成することにしました。

さて、OpenOfficeCalcへの操作をいちいちソース内に書くのは面倒です。
ということで、OpenOfficeCalcへの操作を汎用化したDLLを作成してます。まだ未完成なので問題があるかと思いますが、今回のセルプロパティの部分も含めて載せてみたいと思います。


以前に書いた罫線へのアクセスやセルへのアクセス、デリゲートを使った部分も入っています。(C# .NetFramework2.0)
文字数制限のため、ハイライト無し&&分割して掲載します。
NetからOpenOfficeCalcへの操作を汎用化したDLL(Part1)
NetからOpenOfficeCalcへの操作を汎用化したDLL(Part2)
NetからOpenOfficeCalcへの操作を汎用化したDLL(Part3)


参考:
●Win32API(C言語)編 第13章 色の指定
Service CellProperties
[PR]
by Jehoshaphat | 2011-10-20 02:02 | .Net開発 | Trackback | Comments(0)
(.Net)C#でのべき乗の計算
C#でべき乗を計算する方法ですが、「^」演算子は使えないようです。(VB.Netだと「^」が使えるようです。)
C#で「^」を使うと排他的論理和になるようです。

C#でべき乗計算する場合(VB.Netでも可)、Math.Pow メソッドを使います。

Math.Pow( 2 , 8 ) だと 2の8乗 という意味になります。


参考:
@IT:.NET TIPS C#やVB.NETでべき乗(累乗)を計算するには?
[PR]
by Jehoshaphat | 2011-10-20 00:03 | .Net開発 | Trackback | Comments(0)
(.Net)ジェネリックデリゲート(汎用デリゲート)を使ってみた
(.Net)デリゲートを自作するメリットがようやく分かってきたで、デリゲートの使い方を書きました。


しかし、delegate型の変数を定義しないといけません。
それを簡略化できる定義済みデリゲート(ジェネリックデリゲート)型というものが.Net Framework2.0以降から存在します。

.Net 2.0では Action<T>(T obj) というデリゲート型が用意されています。
ただし、戻り値は void で、引数は1つという制約が有ります。

.Net 3.5ではさらに定義済みデリゲートが強化され、戻り値を返さない Action デリゲート型が引数なしから引数4つまでに対応、また、Func デリゲートという戻り値を返すデリゲート型も実装されました。

使うことができる定義済みデリゲート型の詳細については、@IT:汎用的に使用できる定義済みのデリゲート型は?[C#、VB]に一覧が載っています。

実際に Action デリゲート型を使ってみた例です。(C# .Net 2.0仕様)
.Net Framework2.0 仕様にしているので、メソッドに複数の引数を渡したいときは、クラスでラップしてます。

public partial class Form1 : Form{
//ボタン押下時
private void button6_Click(object sender, EventArgs e){
//Acitonデリゲート型変数に戻り値無しのCalcAddition3メソッドを関連付け
Action<RapObj> act = CalcAddition3;
Calc3(act, 5,10);
}
//ボタン押下時
private void button7_Click(object sender, EventArgs e){
//Acitonデリゲート型変数に戻り値無しのCalcAddition3メソッドを関連付け
Action<RapObj> act = CalcSubtraction3;
Calc3(act, 5,10);
}

/// <summary>デリゲート経由で呼び出される。</summary>
private void CalcAddition3(RapObj act){
Console.WriteLine(act.X + act.Y);
}
/// <summary>デリゲート経由で呼び出される。</summary>
private void CalcSubtraction3(RapObj act){
Console.WriteLine(act.X - act.Y);
}

private void Calc3(Action<RapObj> act, int x,int y) {
try{
 
//いろいろな共通処理...
//共通処理の例としてxとyをインクリメントする
x++; y++;
//.Net 2.0 のActionデリゲートは引数が1個しかとれないのでクラスでラッピング。
RapObj obj = new RapObj();
obj.X = x; obj.Y = y;
//デリゲート経由のメソッド呼び出し
act(obj);
//いろいろな共通処理...
}catch {
//本来はここに例外処理を実装
}
}
}
 
//Actionデリゲートが一つしか引数取れないので、複数に対応できるようこのクラスでラッピング
public class RapObj{
private int iX;
private int iY;
public int X {
get { return iX; }
set { this.iX = value; }
}
public int Y {
get { return iY; }
set { this.iY = value; }
}
}


.Net3.5 で戻り値を返す Func デリゲートを使った例は下記のようになります。(C# .Net3.5以上)
int型引数を二つとり、long型を返すメソッドを呼び出す例です。

//ボタン押下時
private void button7_Click(object sender, EventArgs e){
//Funcデリゲート型変数に戻り値有りのCalcAdditionメソッドを関連付(引数1の型,引数2の型,戻り値の型)
Func<int, int, long> fnc = CalcAddition;
Calc4(fnc, 10, 5);
}
//ボタン押下時
private void button8_Click(object sender, EventArgs e){
//Funcデリゲート型変数に戻り値有りのCalcAdditionメソッドを関連付(引数1の型,引数2の型,戻り値の型)
Func<int, int, long> fnc = CalcSubtraction;
Calc4(fnc, 10, 5);
}
 
/// <summary>計算(足し算)だけ行う。デリゲート経由で呼び出される。</summary>
private long CalcAddition(int x, int y) {
return x + y;
}
/// <summary>計算(引き算)だけ行う。デリゲート経由で呼び出される。</summary>
private long CalcSubtraction(int x, int y) {
return x - y;
}
 
private void Calc4(Func<int,int,long> fnc, int x, int y){
try {
//いろいろな共通処理...
//共通処理の例としてxとyをインクリメントする
x++; y++;
long res = fnc(x, y);
Console.WriteLine("計算結果:" + res);
//いろいろな共通処理...
} catch {
//本来はここに例外処理を実装
}
}

こうみると、引数が0から4まで使える .Net 3.5 以降の定義済みデリゲートは使い道が結構ありそうですね。
ただし、やはりデリゲートを経由してメソッドを呼び出す場合、それらのメソッドの引数、戻りの型が一致してないとダメというのがちょっと使いづらいです。


参考:
IT.NET C# - Action デリゲートを扱うには... (1)
IT.NET C# - Action デリゲートを扱うには... (2)
IT.NET C# - Action デリゲートを扱うには... (3)
ジェネリックなメソッドやデリゲートがもたらす新スタイル - @IT
FuncデリゲートとActionデリゲート - c_sharpの日記
Action<T>を使い倒してみる - パジャマdeブロッガー(myugaruのヲタ日記)
【C#】Action / Func デリゲート - プログラム & 語学 の個人的なメモ - Yahoo!ブログ
[PR]
by Jehoshaphat | 2011-10-19 23:59 | .Net開発 | Trackback | Comments(0)