DataGridとパスワードをつかうためのサンプル

パスワードのマスキングとか

itemRendererにTextInput指定して、displayAsPasswordとかすれば楽っぽいんですけどitemEditorを使う方法で...。

  • labelFunctionのマスキング用の関数を指定
  • itemEditorにPasswordEditor.mxmlみたいなコンポーネントを指定してあげること。TextInputのdisplayAsPassword="true"は必須で

はまりどころしては、PasswordEditor.mxmlなどでtextプロパティなどで値をセットしておかないと、いつの間にか値そのものが"*****"になってしまう点。ソースコードは、昨日のhttp://d.hatena.ne.jp/shogo4405/20090510/1241957645のソースに追加

PasswordEditor.mxml
<?xml version="1.0"?>
<mx:TextInput displayAsPassword="true" xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:creationComplete>
	<![CDATA[
		text = data.name;
	]]>
	</mx:creationComplete>
</mx:TextInput>
Main.mxml
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*">
	<mx:Script>
		<![CDATA[
		import mx.controls.*;
		import mx.collections.*;
		import mx.controls.dataGridClasses.DataGridColumn;

		public function getSexname(item:Object, column:DataGridColumn):String
		{
			var type:Number = item.sex;
			return (type == 0) ? "女性" : "男性";
		};

                // マスキング用の関数
		public function masking(item:Object, column:DataGridColumn):String{
			return new Array(item.name.length + 1).join("*");
		};

		public function debug():void
		{
			trace(list.getItemAt(0).sex);
			trace(list.getItemAt(0).name);
		};

		[Bindable]
		public var list:ArrayCollection =  new ArrayCollection(
			[ { no:1, name:"Taro", sex: 1 }, { no:2, name:"Hanako", name:"Hanako", sex: 0 } ]
		);
		]]>
	</mx:Script>

	<mx:DataGrid width="100%" height="100%" dataProvider="{list}" editable="true">
		<mx:columns>
			<mx:DataGridColumn dataField="no" editable="false" />
			<mx:DataGridColumn dataField="name" labelFunction="{masking}" itemEditor="PasswordEditor" />
			<mx:DataGridColumn dataField="sex" labelFunction="{getSexname}" editorDataField="value" itemEditor="SexEditor" />
		</mx:columns>
	</mx:DataGrid>
	
	<mx:Button click="debug();" />

</mx:Application>

そもそも

そもそもDataGridでパスワード編集させる仕様にするなよ!っていう突っ込みは無です。

DataGridとComboBoxつかうためのサンプル

DataGridの選択エリアにComboBoxを使おうと思って試行錯誤したときのメモ。知らないと難しい...

何も考えないで実装するとこう

以下のようなソースのときに、"sex"カラムが、持っている値は 0 or 1だけど、男性・女性とComboBoxで編集できるようにすることがゴール。

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
		<![CDATA[
		import mx.controls.*;
		import mx.collections.*;

		[Bindable]
		public var list:ArrayCollection =  new ArrayCollection(
			[ { no:1, name:"Taro", sex: 1 }, { no:2, name:"Hanako", name:"Hanako", sex: 0 } ]
		);
		]]>
	</mx:Script>

	<mx:DataGrid width="100%" height="100%" dataProvider="{list}">
		<mx:columns>
			<mx:DataGridColumn dataField="no" />
			<mx:DataGridColumn dataField="name" />
			<mx:DataGridColumn dataField="sex" />
		</mx:columns>
	</mx:DataGrid>

</mx:Application>

labelFunctionを使ってみる

labelFunctionを使うことによって、0→女性。1→男性のようにlabel表記を処理することができます。

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*">
	<mx:Script>
		<![CDATA[
		import mx.controls.*;
		import mx.collections.*;
		import mx.controls.dataGridClasses.DataGridColumn;

		public function getSexname(item:Object, column:DataGridColumn):String
		{
			var type:Number = item.sex;
			return (type == 0) ? "女性" : "男性";
		};

		[Bindable]
		public var list:ArrayCollection =  new ArrayCollection(
			[ { no:1, name:"Taro", sex: 1 }, { no:2, name:"Hanako", name:"Hanako", sex: 0 } ]
		);
		]]>
	</mx:Script>

	<mx:DataGrid width="100%" height="100%" dataProvider="{list}" editable="true">
		<mx:columns>
			<mx:DataGridColumn dataField="no" editable="false" />
			<mx:DataGridColumn dataField="name" editable="false" />
			<mx:DataGridColumn dataField="sex" labelFunction="{getSexname}" />
		</mx:columns>
	</mx:DataGrid>

</mx:Application>

itemEditorを使う

で、最後に。itemEditorを使っています。itemRendererを使う方法もあるんがけどそれは置いておきます...。 editorDataField="value"と、itemEditorに自作のmxmlを置いているのがポイントでしょうか...。

main.mxml
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*">
	<mx:Script>
		<![CDATA[
		import mx.controls.*;
		import mx.collections.*;
		import mx.controls.dataGridClasses.DataGridColumn;

		public function getSexname(item:Object, column:DataGridColumn):String
		{
			var type:Number = item.sex;
			return (type == 0) ? "女性" : "男性";
		};

		[Bindable]
		public var list:ArrayCollection =  new ArrayCollection(
			[ { no:1, name:"Taro", sex: 1 }, { no:2, name:"Hanako", name:"Hanako", sex: 0 } ]
		);
		]]>
	</mx:Script>

	<mx:DataGrid width="100%" height="100%" dataProvider="{list}" editable="true">
		<mx:columns>
			<mx:DataGridColumn dataField="no" editable="false" />
			<mx:DataGridColumn dataField="name" editable="false" />
			<mx:DataGridColumn dataField="sex" labelFunction="{getSexname}" editorDataField="value" itemEditor="SexEditor" />
		</mx:columns>
	</mx:DataGrid>

</mx:Application>

SexEditor.mxml

編集できるようにitemEditorにカスタマイズした、ComboBoxを指定します。

<?xml version="1.0"?>
<mx:ComboBox  xmlns:mx="http://www.adobe.com/2006/mxml">
	<!-- creationCompleteでComboBoxの初期値を設定しています。 -->
	<mx:creationComplete>
	<![CDATA[
	for(var i:int=0, f:int=dataProvider.length; i<f; i++)
	{
		if(dataProvider[i].data == data.sex)
		{
			selectedIndex = i;
			break;
		};
	};
	]]>
	</mx:creationComplete>
	<mx:dataProvider>
		<mx:Array>
			<mx:Object data="0" label="女性" />
			<mx:Object data="1" label="男性" />
		</mx:Array>
	</mx:dataProvider>
</mx:ComboBox>
あと、Object#dataではなく、Object#fooを使う場合

dataProviderの値にdataではなく、fooを使う場合のソースコードは次の通りです。SexEditor.mxmlのみ変更で対応。

<?xml version="1.0"?>
<mx:ComboBox  xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
	<![CDATA[
	public override function get value():Object{
		return selectedItem.foo;
	};
	]]>
	</mx:Script>
	<mx:creationComplete>
	<![CDATA[
	for(var i:int=0, f:int=dataProvider.length; i<f; i++)
	{
		if(dataProvider[i].foo == data.sex)
		{
			selectedIndex = i;
			break;
		};
	};
	]]>
	</mx:creationComplete>
	<mx:dataProvider>
		<mx:Array>
			<mx:Object foo="0" label="女性" />
			<mx:Object foo="1" label="男性" />
		</mx:Array>
	</mx:dataProvider>
</mx:ComboBox>

Amazon.co.jpでまとめ買いをしたいという欲求で...

こんなものつくってみました

Amazon.co.jpでコミックスのまとめ買いをしたいという欲求で、FlexAmazonAPIを利用してつくってみました。検索してドラッグアンドドロップでショッピングカートに突っ込んで、Amazon.co.jpで購入をクリックでAmazonでものが買えます。

気づいたけど

自身の本のまとめ時間の短縮目的で制作したんですが…トータル時間的にはこのアプリをつくっている時間のほうが長い…(--;というわけで、皆さんのまとめ買いの購入時間の短縮につながれば幸いです。

サイトのURL

http://inia.jp/

PEAR-SOAPとFlexからの通信(サーバサイド)

PEAR-SOAPを用いて作られたWebServiceFlexからSOAP通信で呼び出したときのメモです。色々とはまりどころがあったのでその際のメモも一緒に。
サンプルつくるにあたっては、サーバ側(PHP)→クライアント側(Flex)の順番で作成しています。

1.サーバ側の準備

サーバ側に必要なのは、実際のSOAP通信の際に受け口になってくるphp(xml.php)で、今回はメソッドなどを外出ししたかったので、クラスにまとめました(Service.php)。
サーバ側のソースなどは以下の通りで、簡単の為にxml.phpとService.phpをサーバのドキュメントルートに設置しています。http://localhost/xml.phpでアクセスできるようにしています。

xml.php
<?php
require_once 'Service.php';
require_once 'SOAP/Server.php';

$server = new SOAP_Server();
$server->addObjectMap(new Service(), "urn:foo"); // ※1

if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST')
{
    // $server->service($HTTP_RAW_POST_DATA);
    $server->service(file_get_contents('php://stdin')); // ※2
}
else
{
    require_once 'SOAP/Disco.php';

    $disco = new SOAP_DISCO_Server($server, 'foo');
    header("Content-type: text/xml");

    if(isset($_SERVER['QUERY_STRING']) && strcasecmp($_SERVER['QUERY_STRING'], 'wsdl') == 0)
    {
         echo $disco->getWSDL();
    }
    else
    {
        echo $disco->getDISCO();
    }

    exit;
}
Service.php
<?php
class Service
{
     public function __construct()
     {
         $this->__dispatch_map = array();

         $this->__dispatch_map['hello'] = array(
             'in' => array('arg' => 'string'),
             'out' => array('return' => 'string')
         );
     }

     public function hello($string)
     {
         return $string;
     }
}
WSDLの表示

ここまでつくってhttp://localhost/xml.php?wsdlにアクセスすると以下のようにWSDLが表示されればOK!!!

Application.InputBoxでセルが選択できない件

散布図にラベルを追加するマクロ - Thousand Yearsでセルを"A4"とか直接入力しないといけないのめんどくさい。Application.InputBox(Type:=8)とした場合はエクセルのセルをクリックしてセル名を自動挿入してくれる仕様なのだけれども、自分が書いたコードはそうなっていなかった。原因を調べたらApplication.ScreenUpdatingの順番だったので訂正。

セル選択ができない版
' スクリーンの更新をOFF
Application.ScreenUpdating = False

' ラベル開始セルの指定
If (labels Is Nothing) Then
    On Error Resume Next
        Set labels = Application.InputBox(Prompt:="ラベル開始セル名を入力してください。例)A1", Type:=8)
        If (Err.Number <> 0) Then
            Exit Function
        End If
    On Error GoTo 0
End If
セル選択ができる版
' ラベル開始セルの指定
If (labels Is Nothing) Then
    On Error Resume Next
        Set labels = Application.InputBox(Prompt:="ラベル開始セル名を入力してください。例)A1", Type:=8)
        If (Err.Number <> 0) Then
            Exit Function
        End If
    On Error GoTo 0
End If

' スクリーンの更新をOFF
Application.ScreenUpdating = False

そうなんですね...。

散布図にラベルを追加するマクロ

散布図のポイントにラベルを追加したい

Excelで散布図をかいたときにポイントにラベルを追加したいんですがなかなかうまくいかないので思い悩んだあげくVBAで解決したので、その際のスクリプトをかいたので公開しておきます。
方法を調べていったら、斜めにデータを配置するのがオーソドックスなやりかたみたいですね。ttp://pc.nikkeibp.co.jp/article/NPC/20060628/242035/

使い方と前提条件

マクロ実行時に「セル名を入力を促すダイアログ」が出てきますが、そのときはラベル名の一番最初のセル名を入力してください。この例では、B3を指定するとラベルが自動的に振られます。条件としてテーブルのフォーマットはサンプルのような{ラベル名,X,Y},{ラベル名,Y,X}とかそういう表を前提としています。

マクロ実行前

マクロ実行後


ソースコード*1

Public Sub 散布図にラベルを追加する()
    AttachLabelsToPoint
End Sub

Private Function AttachLabelsToPoint(Optional labels As range = Nothing)

	Dim i As Integer, j As Integer

    If (ActiveChart Is Nothing) Then
        MsgBox ("アクティブなグラフはありません。" & Chr(10) & Chr(13) & "ラベルを追加するグラフを選んでください。")
        Exit Function
    End If

    ' ラベル開始セルの指定
    If (labels Is Nothing) Then
        On Error Resume Next
            Set labels = Application.InputBox(Prompt:="ラベル開始セル名を入力してください。例)A1", Type:=8)
            If (Err.Number <> 0) Then
                Exit Function
            End If
        On Error GoTo 0
    End If

    ' スクリーンの更新をOFF
    Application.ScreenUpdating = False

    ' ラベルの記入処理
    For i = 1 To ActiveChart.SeriesCollection.Count
        For j = 1 To ActiveChart.SeriesCollection(i).points.Count
            ActiveChart.SeriesCollection(i).points(j).HasDataLabel = True
            ActiveChart.SeriesCollection(i).points(j).DataLabel.Text = labels.Offset(j - 1, 0).Value
        Next j
    Next i

End Function

追記

*1:にわかVBAerなので突っ込み歓迎

漢数字をアラビア数字に変換とか(突貫工事)

漢数字をアラビア数字に

一か八かとか、万が一。百子(人命)とか機械的に変換してしまわないように、一桁の数字は排除して漢数字をアラビア数字に変換するプログラム。突貫工事。
(JSで実装したんだけど欲しいのはPerlのプログラム...。)

ソース

"フランス料理のコース二千五百円(サービス料金加えて三千円)三名様より".toArabiaSuuji();
// "フランス料理のコース2500円(サービス料金加えて3000円)三名様より"

(function()
{
    var base = {"零":0, "一":1,"二":2,"三":3,"四":4,"五":5,"六":6,"七":7,"八":8,"九":9};
    var mult = {"十":10, "拾":10, "百":100, "千":1000,"万":10000,"億":100000,"兆":1000000};

    String.prototype.toArabiaSuuji = function()
    {
    	var i, ch, stack = [], inner = false, buf = this.split('');

    	for(i=buf.length;0<=i;i--)
        {
        	if(inner)
            {
            	ch = mult[buf[i]];
            	if(ch)
                {
                	stack.push('+', ch);
                	buf[i] = '';
                	continue;
                };

            	ch = base[buf[i]];
            	if(ch)
                {
                	stack.push('*', ch);
                	buf[i] = '';
                	continue;
                };

            	if(stack.length)
                {
                	buf[i+1] = eval(stack.join(''));
                	stack = [];
                };

            	inner = false;
            }
        	else
            {
            	ch = mult[buf[i]];
            	if(ch)
                {
                	stack.push(ch);
                	ch = base[buf[i+1]];
                	if(ch)
                    {
                    	stack = [ch, '+'].concat(stack);
                    	buf[i+1] = '';
                    };
                	buf[i] = '', inner = true;
                	continue;
                };
            };
        };

    	if(stack.length)
        {
        	buf[0] = eval(stack.join(""));
        };

    	return buf.join('');
    };
})();


ToDo

追記

一億五千万円とかまったく出来ないでのやり直し。