我需要将flex 4.5中的饼图和数据网格导出为Microsoft Excel格式。我能够使用as3xls导出数据网格。但它不允许导出任何图表,甚至不能将图像添加到Excel文件中。任何人都可以推荐我这样做的方法吗?
答案 0 :(得分:1)
据我所知,无法通过现有库将图表导出到Excel。
我想建议你一个特定的方法来做到这一点。我们都知道当前的Office文件存储为XML结构的集合。这些文件打包为zip-archive。如果您看一下这些东西,您可以看到可以操纵这些文件中的某些行来获取任何表格,任何图表,您想要的任何图片。
要在Flex中执行此操作,您需要基本的XML结构和一些库才能压缩结果。
我使用Nochump组件来访问zip函数。
Here您可以阅读有关Excel文件结构的信息。
以下是一些图片,显示了使用此方法可以获得的结果。
关于应用程序,您应该知道必须修补哪些文件:
为了使它工作,我创建了一个XML结构,其中包含Excel文件树的描述。我放入项目文件夹的这个文件树的实际XML文件。然后我将所有文件读取到ArrayCollection并操纵其中三个文件的数据。
毕竟我将它们打包成zip-archive并让用户将其保存到PC中。
以下是源代码:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600"
creationComplete="onCreationComplete(event)">
<fx:Declarations>
<fx:XML id="fileTree" xmlns="">
<root id=''>
<folder id='_rels'>
<file id='.rels'/>
</folder>
<folder id='docProps'>
<file id='app.xml'/>
<file id='core.xml'/>
</folder>
<folder id='xl'>
<folder id='_rels'>
<file id='workbook.xml.rels'/>
</folder>
<folder id='charts'>
<file id='chart1.xml'/>
</folder>
<folder id='drawings'>
<folder id='_rels'>
<file id='drawing1.xml.rels'/>
</folder>
<file id='drawing1.xml'/>
</folder>
<folder id='theme'>
<file id='theme1.xml'/>
</folder>
<folder id='worksheets'>
<folder id='_rels'>
<file id='sheet1.xml.rels'/>
</folder>
<file id='sheet1.xml'/>
</folder>
<file id='sharedStrings.xml'/>
<file id='styles.xml'/>
<file id='workbook.xml'/>
</folder>
<file id='[Content_Types].xml'/>
</root>
</fx:XML>
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.utils.ByteArray;
import mx.collections.ArrayCollection;
import mx.collections.XMLListCollection;
import mx.controls.Alert;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.events.FlexEvent;
import mx.rpc.xml.SimpleXMLDecoder;
import nochump.util.zip.*;
private const CELL_LETTERS:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private var xmlLoader:URLLoader = new URLLoader();
private var loaderItemId:int = 0;
private var rootPath:String = "com/excelchart/xmlsource/";
private var xlsxFiles:ArrayCollection = new ArrayCollection();
[Bindable]private var dp:ArrayCollection = new ArrayCollection([
{party:"SPD", y2009:23, y2005:34.2 },
{party:"CDU", y2009:27.3, y2005:27.8 },
{party:"FDP", y2009:14.6, y2005:9.8 },
{party:"The Left Party", y2009:11.9, y2005:8.7 },
{party:"A90/The Greens", y2009:10.7, y2005:8.1 },
{party:"CSU", y2009:6.5, y2005:7.4 },
{party:"Others", y2009:6, y2005:3.9 }]);
protected function onCreationComplete(event:FlexEvent):void
{
init();
traverseXMLList(fileTree, 0, "");
processNextNode();
}
private function traverseXMLList(xml:XML, depth:int, parentPath:String):void
{
var path:String = (parentPath == "") ? xml.@id : parentPath + "/" + xml.@id;
var nodeType:String = xml.name().localName;
xlsxFiles.addItem({name:xml.@id.toString(), type:nodeType, path:path});
for each (var item:XML in xml.children())
traverseXMLList(item, depth + 1, path);
}
private function packZip():void
{
var zipEntry:ZipEntry;
var fileName:String;
var fileData:ByteArray = new ByteArray();
var zipOut:ZipOutput = new ZipOutput();
for (var i:int = 0; i < xlsxFiles.length; i++)
{
var obj:Object = xlsxFiles.getItemAt(i);
if (obj.type == "file")
{
fileName = obj.path;
zipEntry = new ZipEntry(fileName);
fileData.clear();
fileData.writeUTFBytes(obj.content);
zipOut.putNextEntry(zipEntry);
zipOut.write(fileData);
zipOut.closeEntry();
}
}
// end the zip
zipOut.finish();
var file:FileReference = new FileReference();
file.save(zipOut.byteArray, "chart.xlsx");
}
private function init():void
{
xmlLoader.addEventListener(Event.COMPLETE, onXmlLoaderComplete);
xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, onXmlLoaderIOError);
}
private function loadXML():void
{
xmlLoader.load(new URLRequest(rootPath + xlsxFiles.getItemAt(loaderItemId).path));
}
private function onXmlLoaderComplete(event:Event):void
{
xlsxFiles.getItemAt(loaderItemId).content = (event.currentTarget as URLLoader).data;
processNextNode();
}
private function processNextNode():void
{
if (xlsxFiles.length > loaderItemId + 1)
{
loaderItemId++;
if (xlsxFiles.getItemAt(loaderItemId).type == "file")
loadXML();
else
processNextNode();
}
else
this.btnMakeZip.enabled = true;
}
private function onXmlLoaderIOError(evt:IOErrorEvent):void
{
Alert.show("error!");
}
protected function onMakeZipClick(event:MouseEvent):void
{
parseDataGrid();
packZip();
}
protected function isString(input:String):Boolean
{
return isNaN(Number(input));
}
protected function parseDataGrid():void
{
function getStringId(str:String):int
{
var result:int = -1;
for (var i:int = 0; i < stringDictionary.length; i++)
if (stringDictionary.getItemAt(i) == str)
{
result = i;
break;
}
if (result == -1)
{
stringDictionary.addItem(str);
result = stringDictionary.length - 1;
}
return result;
}
//find sheet1 xml
var sheet1XML:XML;
var xlsxFilesItemId:int;
for (i = 0; i < xlsxFiles.length; i++)
if (xlsxFiles.getItemAt(i).name == "sheet1.xml")
{
sheet1XML = new XML(xlsxFiles.getItemAt(i).content);
xlsxFilesItemId = i;
break;
}
//define the size of the DG
var dgHeight:int = myGrid.dataProvider.length;
var dgWidth:int = myGrid.columns.length;
//namespaces for elements
var mainNS:Namespace = new Namespace("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
var x14acNS:Namespace = new Namespace("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");
default xml namespace = mainNS;
sheet1XML.addNamespace(x14acNS);
sheet1XML.dimension.@ref = "A1:" + CELL_LETTERS.charAt(dgWidth) + (dgHeight + 1).toString();
//delete nodes from sheet1XML.sheetData
var sheetDataRowCollection:XMLListCollection = new XMLListCollection(sheet1XML.sheetData.row);
sheetDataRowCollection.removeAll();
//create a String dictionary
var stringDictionary:ArrayCollection = new ArrayCollection();
var stringId:int = 0;
var cellNode:XML, rowNode:XML, value:String, cellAddress:String;
var i:int, j:int;
//add head information
rowNode = new XML();
rowNode.addNamespace(mainNS);
rowNode.addNamespace(x14acNS);
rowNode = <row r="1" spans="1:3"/>;
rowNode.@x14acNS::dyDescent = "0.25";
for (j = 0; j < dgWidth; j++)
{
value = (((myGrid.columns as ArrayList).getItemAt(j) as GridColumn).headerText).toString();
cellAddress = CELL_LETTERS.charAt(j) + "1";
cellNode = new XML();
cellNode = <c r={cellAddress} t="s"><v>{getStringId(value).toString()}</v></c>;
rowNode = rowNode.appendChild(cellNode);
}
sheetDataRowCollection.addItem(rowNode);
//traverse through DG
for (i = 0; i < dgHeight; i++)
{
rowNode = new XML();
rowNode.addNamespace(mainNS);
rowNode.addNamespace(x14acNS);
rowNode = <row r={i + 2} spans="1:3"/>;
rowNode.@x14acNS::dyDescent = "0.25";
for (j = 0; j < dgWidth; j++)
{
value = (myGrid.dataProvider.getItemAt(i)[((myGrid.columns as ArrayList).getItemAt(j) as GridColumn).dataField]).toString();
cellAddress = CELL_LETTERS.charAt(j) + (i+2).toString();
cellNode = new XML();
if (isString(value))
cellNode = <c r={cellAddress} t="s"><v>{getStringId(value).toString()}</v></c>;
else
cellNode = <c r={cellAddress}><v>{value}</v></c>;
rowNode = rowNode.appendChild(cellNode);
}
sheetDataRowCollection.addItem(rowNode);
}
//save sheet1 to xlsxFiles
xlsxFiles.getItemAt(xlsxFilesItemId).content = sheet1XML;
//sharedStrings
var sharedStringsXML:XML;
for (i = 0; i < xlsxFiles.length; i++)
if (xlsxFiles.getItemAt(i).name == "sharedStrings.xml")
{
sharedStringsXML = new XML(xlsxFiles.getItemAt(i).content);
xlsxFilesItemId = i;
break;
}
//delete nodes from sharedStrings.xml
var sharedStringsCollection:XMLListCollection = new XMLListCollection(sharedStringsXML.si);
sharedStringsCollection.removeAll();
//fill the sharedStrings XML
sharedStringsXML.@count = stringDictionary.length;
sharedStringsXML.@uniqueCount = stringDictionary.length;
//var siNode:XML;
for each (var str:String in stringDictionary)
sharedStringsXML.appendChild(<si><t>{str}</t></si>);
//save sharedStrings to xlsxFiles
xlsxFiles.getItemAt(xlsxFilesItemId).content = sharedStringsXML;
//chart1
var chart1XML:XML;
for (i = 0; i < xlsxFiles.length; i++)
if (xlsxFiles.getItemAt(i).name == "chart1.xml")
{
chart1XML = new XML(xlsxFiles.getItemAt(i).content);
xlsxFilesItemId = i;
break;
}
var catLetter:String = CELL_LETTERS.charAt(cbCategories.selectedIndex);
var catAddress:String = "Tabelle1!$" + catLetter + "$2:$" + catLetter + "$" + (dgHeight + 1).toString();
var valLetter:String = CELL_LETTERS.charAt(cbValues.selectedIndex);
var valAddress:String = "Tabelle1!$" + valLetter + "$2:$" + valLetter + "$" + (dgHeight + 1).toString();
default xml namespace = new Namespace("c", "http://schemas.openxmlformats.org/drawingml/2006/chart");
chart1XML.chart.plotArea.pieChart.ser.cat.strRef.f = catAddress;
chart1XML.chart.plotArea.pieChart.ser.val.numRef.f = valAddress;
xlsxFiles.getItemAt(xlsxFilesItemId).content = chart1XML;
//switch back to the default namespace
default xml namespace = new Namespace("");
}
private function onBtnRefresh():void
{
this.mySeries.nameField = cbCategories.selectedItem.dataField;
this.mySeries.field = cbValues.selectedItem.dataField;
}
]]>
</fx:Script>
<s:HGroup x="100" y="50">
<s:VGroup>
<s:DataGrid id="myGrid" width="360" dataProvider="{dp}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="party" headerText="Party"/>
<s:GridColumn dataField="y2005" headerText="2005" width="90"/>
<s:GridColumn dataField="y2009" headerText="2009" width="90"/>
</s:ArrayList>
</s:columns>
</s:DataGrid>
<s:HGroup verticalAlign="bottom">
<s:Label text="Categories:" width="70"/>
<s:ComboBox id="cbCategories" dataProvider="{myGrid.columns}" labelField="headerText" selectedIndex="0"/>
</s:HGroup>
<s:HGroup verticalAlign="bottom">
<s:Label text="Values:" width="70"/>
<s:ComboBox id="cbValues" dataProvider="{myGrid.columns}" labelField="headerText" selectedIndex="1"/>
</s:HGroup>
<s:HGroup>
<s:Button id="btnRefresh" label="Bild Chart" click="onBtnRefresh()"/>
<s:Button id="btnMakeZip" label="Export" enabled="false" click="onMakeZipClick(event)"/>
</s:HGroup>
</s:VGroup>
<mx:PieChart id="myChart" width="281" height="277" dataProvider="{dp}" showDataTips="true">
<mx:series>
<mx:PieSeries id="mySeries" field="y2005" nameField="party" labelPosition="inside" explodeRadius=".12" />
</mx:series>
</mx:PieChart>
<mx:Legend dataProvider="{myChart}"/>
</s:HGroup>
</s:Application>
我希望它可以帮到你。 感谢有趣的问题!