1

I am new to Flex coding and am trying to import an Excel file so that I can work with it later. I've cobbled enough together from the two articles below so that I can successfully load one Excel file and display the contents in a DataGrid.

However, if I try to upload a second Excel file, the contents of the DataGrid don't change. (And I end up truncating one row from the top, when the code re-writes the headers to the DataGrid.)

  1. http://blog.flexexamples.com/2007/09/21/uploading-files-in-flex-using-the-filereference-class
  2. http://code.google.com/p/as3xls/wiki/Tutorial

Full code is below. Any thoughts on where I'm going wrong?

Cheers and thanks in advance!

Corey

PS: There is a glitch in how I'm handling the headers, as any formulae in the Excel sheet still reference the original row after I remove the headers. They are pointing to one row below where they should.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" xmlns="*" creationComplete="init()" height="727" width="777">

<mx:Script>

    <![CDATA[
        import com.as3xls.xls.ExcelFile;
        import com.as3xls.xls.Sheet;

        import mx.collections.ArrayCollection;

        //Based on example from: http://blog.flexexamples.com/2007/09/21/uploading-files-in-flex-using-the-filereference-class/

        private var fileRef:FileReference;
        private var ba:ByteArray;
        private var xlFile:ExcelFile;
        private var hdrs:Array;
        private var runOnce:Boolean;


        [Bindable]
        private var xlsheet:ArrayCollection;

        private const FILE_URL:String = "http://localhost:8500/fileref/uploader.cfm";
        private const XLS_FILTER:FileFilter = new FileFilter("EXCEL FILES (*.xls, *.xlsx)", "*.xls; *.xlsx");
        private const TXT_FILTER:FileFilter = new FileFilter("TEXT FILES (*.txt, *.csv, *.tsv)", "*.txt; *.csv; *.tsv");
        private const ALL_FILTER:FileFilter = new FileFilter("ALL FILES (*.*)", "*.*");

        private function init():void {
            fileRef = new FileReference();
            fileRef.addEventListener(Event.SELECT, fileRef_select);
            fileRef.addEventListener(ProgressEvent.PROGRESS, fileRef_progress);
            fileRef.addEventListener(Event.COMPLETE, fileRef_complete);

            ba = new ByteArray();
            xlFile = new ExcelFile();
            hdrs = new Array();
            xlsheet = new ArrayCollection();
        }

        private function browseAndUpload():void {
            fileRef.browse([XLS_FILTER, TXT_FILTER, ALL_FILTER]);
            message.text = "";


        }

        private function fileRef_select(evt:Event):void {
            try {
                message.text = "size (bytes): "+ numberFormatter.format(fileRef.size);
                message.text += " | " + fileRef.name

                //Alert.show (fileRef.name);
                fileRef.load();

            } catch(err:Error) {
                message.text = "ERROR: zero-byte file";
            }
        }

        private function fileRef_progress(evt:ProgressEvent):void{
            progressBar.visible = true;
        }

        private function fileRef_complete(evt:Event):void{

            try {
                message.text += " (complete)";
                progressBar.visible = false;
                grid.initialize()               

                ba=fileRef["data"];
                xlFile.loadFromByteArray(ba);
                xlsheet = xlFile.sheets[0].values;

                hdrs =  xlsheet[0];
                xlsheet.removeItemAt(0);

                grid.dataProvider = xlsheet;
            } catch (err:Error) {
                message.text = "An error occurred";
            }

        }

        private function updateHeaders(): void {
            if(grid.columnCount>=1){
                for (var i:int=0; i<=grid.columnCount-1; i++){
                    grid.columns[i].headerText=hdrs[i];
                }

            }
        }

    ]]>

</mx:Script>

<mx:NumberFormatter id="numberFormatter"/>
<mx:Button label="Upload File"
           click="browseAndUpload();" labelPlacement="left"/>
<mx:Label id="message"/>
<mx:ProgressBar id="progressBar"
                indeterminate="true"
                visible = "false"/>

<mx:DataGrid id="grid"
    updateComplete="updateHeaders();"/>


</mx:Application>
corey_s
  • 13
  • 4
  • Appologies, just noticed that some of the code got truncated at the bottom, tho I suspect nothing of significance to the issue. Also a few excess variables left over from attempts to solve this... – corey_s Dec 15 '12 at 23:55
  • I fixed the code formatting; sometimes StackOverflow gets weird on code formatting. I'm not sure why grid.initialize() is called; you should never need to call that manually. If the DataGrid isn't changing it most likely means that the dataProvider is either not getting changed or is being replaced w/ the same element. The reason the top item is being removed is because of xmlSheet.removeItemAt(0). Sounds like you're not selecting a new file or that the fileRef is not getting a refernece to the new file. – JeffryHouser Dec 16 '12 at 05:50
  • @www.Flextras.com, thanks for touching up the code formatting. Couldn't see how to do that myself. – corey_s Dec 16 '12 at 15:26
  • I attempted the `grid.initialize()` call in an attempt to flush out old values. Clearly didn't clean up completely before I posted. (sorry). I knew that was the issue with the `xlSheet.removeItemAt(0)` call, causing the rows to be truncated. I feel like that's a clue to my problem. Seems like `xlSheet` is not being updated, but I'm not sure if that's a problem with the `fileRef.load()` call, or `xlSheet` not accepting a new value. The COMPLETE event is being fired; still no new data. – corey_s Dec 16 '12 at 15:32
  • Is the problem that the var isn't being updated or the DataGrid? IE if you break after the file is loaded, do you see the expected values? – ethrbunny Dec 16 '12 at 16:18
  • .. and what happens if you make the variable Bindable and link it to the DataGrid? – ethrbunny Dec 16 '12 at 16:19
  • @corey_s You can format code w/ the curly bracket button in th editor. I think you did that. But, sometimes the code formatting will "get lost" especially if you hit enter or tweak things after signing in. Looks like someone already posted your solution. – JeffryHouser Dec 16 '12 at 17:56
  • One other thing, to refres the grid; you should make use of the invalidation methods: invalidateDisplayList(), invalidateSize(), and invalidateProperties(). The MX List based classes also have an invalidateList() method. Spark classes also have an invalidateSkinState() method. – JeffryHouser Dec 16 '12 at 17:57

1 Answers1

2

The only error in your code is that the xlFile object is incremented each time you load a new stuff. So the sheets[0] is always the same! If your files have 3 sheets, then the first sheet of the new file is in the sheets[3] object.

To correct this try to initiate the xlFile object every time you load a new file. I have done it by me and it works perfectly! Here is my code (I have wiped some lines to simplify it)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:mx="library://ns.adobe.com/flex/mx" 
            layout="vertical" 
            height="727" width="777" creationComplete="init()">

<fx:Script>
    <![CDATA[
        import com.as3xls.xls.ExcelFile;
        import com.as3xls.xls.Sheet;
        import mx.collections.ArrayCollection;

        private var fileRef:FileReference;
        private var ba:ByteArray;
        private var xlFile:ExcelFile;
        private var hdrs:Array;
        private var runOnce:Boolean;

        [Bindable]private var xlsheet:ArrayCollection;

        private const XLS_FILTER:FileFilter = new FileFilter("EXCEL FILES (*.xls)", "*.xls");

        private function init():void 
        {
            fileRef = new FileReference();
            fileRef.addEventListener(Event.SELECT, fileRef_select);
            fileRef.addEventListener(ProgressEvent.PROGRESS, fileRef_progress);
            fileRef.addEventListener(Event.COMPLETE, fileRef_complete);

            ba = new ByteArray();
            hdrs = new Array();
            xlsheet = new ArrayCollection();
        }

        private function browseAndUpload():void {
            fileRef.browse([XLS_FILTER]);
            message.text = "";
        }

        private function fileRef_select(evt:Event):void {
            try {
                message.text = "size (bytes): "+ fileRef.size;
                message.text += " | " + fileRef.name
                fileRef.load();
            } catch(err:Error) {
                message.text = "ERROR: zero-byte file";
            }
        }

        private function fileRef_progress(evt:ProgressEvent):void{
            progressBar.visible = true;
        }

        private function fileRef_complete(evt:Event):void{
            try {
                xlFile = new ExcelFile();

                message.text += " (complete)";
                progressBar.visible = false;

                ba=fileRef["data"];
                xlFile.loadFromByteArray(ba);
                xlsheet = xlFile.sheets[0].values;

                hdrs =  xlsheet[0];
                xlsheet.removeItemAt(0);

                grid.dataProvider = xlsheet;
            } catch (err:Error) {
                message.text = "An error occurred";
            }
        }

        private function updateHeaders(): void {
            if(grid.columnCount>=1){
                for (var i:int=0; i<=grid.columnCount-1; i++){
                    grid.columns[i].headerText=hdrs[i];
                }
            }
        }

    ]]>
</fx:Script>

<mx:Button label="Upload File" click="browseAndUpload();" labelPlacement="left"/>
<mx:Label id="message"/>
<mx:ProgressBar id="progressBar" indeterminate="true" visible = "false"/>
<mx:DataGrid id="grid" updateComplete="updateHeaders();"/>
</mx:Application>
Anton
  • 4,544
  • 2
  • 25
  • 31
  • awesome... That did it. Thanks! I figured it had to be something simple like that. Now I just need to find a better way to handle the headers so any formulae don't get messed up. – corey_s Dec 16 '12 at 18:25
  • missed the hashtag in the last comment. Just wanted to pass on my thanks! – corey_s Dec 16 '12 at 18:31