試用過(guò)Google Spreadsheets的朋友,可能發(fā)現(xiàn)其一個(gè)有意思的特性,我們可以直接將Excel中的多行數(shù)據(jù)直接復(fù)制插入到Google Spreadsheets中(OpenOffice也可以直接復(fù)制過(guò)去),沒(méi)嘗試過(guò)的朋友可以馬上按如下步驟測(cè)試下:
在Excel(或OpenOffice Calc)中選擇多行數(shù)據(jù),敲Ctrl+C鍵,復(fù)制選擇的多行數(shù)據(jù):
然后到Google Spreadsheets,敲Ctrl+V鍵,前面復(fù)制的單元格就被復(fù)制過(guò)來(lái)了:
這是如何做到的呢?其實(shí)很簡(jiǎn)單,在Excel(OpenOffice Calc)中,當(dāng)多個(gè)單元格被復(fù)制時(shí),這些單元格的數(shù)據(jù)是以tab鍵分隔一行行數(shù)據(jù)(tab-separated values (TSV))存放在剪貼板中的,當(dāng)這些數(shù)據(jù)被粘貼到Google Spreadsheets中時(shí),這些TSV格式的數(shù)據(jù)被解析并被相應(yīng)插入到Google Spreadssheets中了。
既然知道其中的奧妙,那么剩下的就是在Flex中實(shí)現(xiàn)同樣的效果了。以下是我們的實(shí)現(xiàn)思路,可以在Excel和Flex相互直接復(fù)制粘貼數(shù)據(jù)。
我們的思路的精妙所在是隱藏文本(TextField)組件的使用:
- 在DataGrid中,當(dāng)按下Ctrl鍵時(shí),我們創(chuàng)建一個(gè)隱藏的文本(TextField)組件,并將焦點(diǎn)定位給它,這樣,我們就可以接受任何通過(guò)Ctrl+V粘貼過(guò)來(lái)的數(shù)據(jù)。相應(yīng)的我們也將DataGrid選擇行數(shù)據(jù)以TSV格式拷貝到TextField組件中,并且將所有的文本選擇,這樣我們使用Ctrl+C操作就可以復(fù)制當(dāng)前行所有數(shù)據(jù)了。
- 監(jiān)聽(tīng)隱藏文件組件的textInput事件。如果有任何數(shù)據(jù)被粘貼的話,那么在這里數(shù)據(jù)將被解析,并插入到DataGrid中。
- 當(dāng)Ctrl鍵釋放后,移除隱藏的文本組件。
以下是完整實(shí)現(xiàn)示例代碼:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import flash.events.KeyboardEvent;
private function dataGridKeyDownHandler(event:KeyboardEvent):void
{
if (event.ctrlKey && !dataGrid.getChildByName("clipboardProxy"))
{
// Add an invisible TextField object to the DataGrid
var textField:TextField = new TextField();
textField.name = "clipboardProxy";
dataGrid.addChild(textField);
textField.visible = false;
textField.type = TextFieldType.INPUT;
textField.multiline = true;
// Populate the TextField with selected data in TSV format
textField.text = getTextFromItems(dataGrid.selectedItems);
textField.setSelection(0, textField.text.length - 1);
// Listen for textInput event
textField.addEventListener(TextEvent.TEXT_INPUT,
clipboardProxyPasteHandler);
// Set player-level focus to the TextField
systemManager.stage.focus = textField;
}
}
private function dataGridKeyUpHandler(event:KeyboardEvent):void
{
if (!event.ctrlKey)
{
var textField:TextField = TextField(dataGrid
.getChildByName("clipboardProxy"));
if (textField)
dataGrid.removeChild(textField);
}
}
private function clipboardProxyPasteHandler(event:TextEvent):void
{
// Extract values from TSV format and populate the DataGrid
var items:Array = getItemsFromText(event.text);
for each (var item:Object in items)
dataGrid.dataProvider.addItem(item);
}
private function getItemsFromText(text:String):Array
{
var rows:Array = text.split("\n");
if (!rows[rows.length - 1])
rows.pop();
var columns:Array = dataGrid.columns;
var itemsFromText:Array = [];
for each (var rw:String in rows)
{
var fields:Array = rw.split("\t");
var n:int = Math.min(columns.length, fields.length);
var item:Object = {};
for (var i:int = 0; i < n; i++)
item[columns[i].dataField] = fields[i];
itemsFromText.push(item);
}
return itemsFromText;
}
private function getTextFromItems(items:Array):String
{
var columns:Array = dataGrid.columns;
var textFromItems:String = "";
for each (var it:Object in items)
{
for each (var c:DataGridColumn in columns)
textFromItems += it[c.dataField] + "\t";
textFromItems += "\n";
}
return textFromItems;
}
]]>
</mx:Script>
<mx:DataGrid id="dataGrid" editable="true"
keyDown="dataGridKeyDownHandler(event)"
keyUp="dataGridKeyUpHandler(event)">
<mx:columns>
<mx:DataGridColumn headerText="Scheduled Date"
dataField="scheduledDate" />
<mx:DataGridColumn headerText="Home Team"
dataField="homeTeam" />
<mx:DataGridColumn headerText="Away Team"
dataField="awayTeam" />
<mx:DataGridColumn headerText="Field"
dataField="field" />
</mx:columns>
<mx:dataProvider>
<mx:Object scheduledDate="4/1/2006" homeTeam="Chester Bucks"
awayTeam="Long Valley Hitters" field="Dawn Field" />
</mx:dataProvider>
</mx:DataGrid>
</mx:Application>
運(yùn)行實(shí)例(FlashPlayer9.0)
以下是最終實(shí)現(xiàn)的效果圖:
原文:Copy 'n paste between Excel and Flex