/**
         * Writes out the MsoDrawing records and Obj records for each image
         * and chart on the sheet
         *
         * @param outputFile the output file
         * @exception IOException
         */
        public void write(File outputFile)
        {
            // If there are no drawings or charts on this sheet then exit
            if (drawings.Count == 0 && charts.Length == 0)
            {
                return;
            }

            // See if any drawing has been modified
            bool modified  = drawingsModified;
            int  numImages = drawings.Count;

            foreach (DrawingGroupObject d in drawings)
            {
                if (d.getOrigin() != Origin.READ)
                {
                    modified = true;
                }
            }

            // If the drawing order has been muddled at all, then we'll need
            // to regenerate the Escher drawing data
            if (numImages > 0 && !modified)
            {
                DrawingGroupObject d2 = (DrawingGroupObject)drawings[0];
                if (!d2.isFirst())
                {
                    modified = true;
                }
            }

            // Check to see if this sheet consists of just a single chart.  If so
            // there is no MsoDrawingRecord, so write out the data and exit
            if (numImages == 0 &&
                charts.Length == 1 &&
                charts[0].getMsoDrawingRecord() == null)
            {
                modified = false;                 // this sheet has not been modified
            }
            // If no drawing has been modified, then simply write them straight out
            // again and exit
            if (!modified)
            {
                writeUnmodified(outputFile);
                return;
            }

            object[]        spContainerData  = new object[numImages + charts.Length];
            int             length           = 0;
            EscherContainer firstSpContainer = null;

            // Get all the spContainer byte data from the drawings
            // and store in an array
            for (int i = 0; i < numImages; i++)
            {
                DrawingGroupObject drawing = (DrawingGroupObject)drawings[i];

                EscherContainer spc = drawing.getSpContainer();

                if (spc != null)
                {
                    byte[] data = spc.getData();
                    spContainerData[i] = data;

                    if (i == 0)
                    {
                        firstSpContainer = spc;
                    }
                    else
                    {
                        length += data.Length;
                    }
                }
            }

            // Get all the spContainer bytes from the charts and add to the array
            for (int i = 0; i < charts.Length; i++)
            {
                EscherContainer spContainer = charts[i].getSpContainer();
                byte[]          data        = spContainer.getBytes(); //use getBytes instead of getData
                data = spContainer.setHeaderData(data);
                spContainerData[i + numImages] = data;

                if (i == 0 && numImages == 0)
                {
                    firstSpContainer = spContainer;
                }
                else
                {
                    length += data.Length;
                }
            }

            // Put the generalised stuff around the first item
            DgContainer dgContainer = new DgContainer();
            Dg          dg          = new Dg(numImages + charts.Length);

            dgContainer.add(dg);

            SpgrContainer spgrContainer = new SpgrContainer();

            SpContainer _spContainer = new SpContainer();
            Spgr        spgr         = new Spgr();

            _spContainer.add(spgr);
            Sp sp = new Sp(ShapeType.MIN, 1024, 5);

            _spContainer.add(sp);
            spgrContainer.add(_spContainer);

            spgrContainer.add(firstSpContainer);

            dgContainer.add(spgrContainer);

            byte[] firstMsoData = dgContainer.getData();

            // Adjust the length of the DgContainer
            int len = IntegerHelper.getInt(firstMsoData[4],
                                           firstMsoData[5],
                                           firstMsoData[6],
                                           firstMsoData[7]);

            IntegerHelper.getFourBytes(len + length, firstMsoData, 4);

            // Adjust the length of the SpgrContainer
            len = IntegerHelper.getInt(firstMsoData[28],
                                       firstMsoData[29],
                                       firstMsoData[30],
                                       firstMsoData[31]);
            IntegerHelper.getFourBytes(len + length, firstMsoData, 28);

            // Now write out each MsoDrawing record

            // First MsoRecord
            // test hack for form objects, to remove the ClientTextBox record
            // from the end of the SpContainer
            if (numImages > 0 &&
                ((DrawingGroupObject)drawings[0]).isFormObject())
            {
                byte[] msodata2 = new byte[firstMsoData.Length - 8];
                System.Array.Copy(firstMsoData, 0, msodata2, 0, msodata2.Length);
                firstMsoData = msodata2;
            }

            MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData);

            outputFile.write(msoDrawingRecord);

            if (numImages > 0)
            {
                DrawingGroupObject firstDrawing = (DrawingGroupObject)drawings[0];
                firstDrawing.writeAdditionalRecords(outputFile);
            }
            else
            {
                // first image is a chart
                Chart     chart     = charts[0];
                ObjRecord objRecord = chart.getObjRecord();
                outputFile.write(objRecord);
                outputFile.write(chart);
            }

            // Now do all the others
            for (int i = 1; i < spContainerData.Length; i++)
            {
                byte[] bytes = (byte[])spContainerData[i];

                // test hack for form objects, to remove the ClientTextBox record
                // from the end of the SpContainer
                if (i < numImages &&
                    ((DrawingGroupObject)drawings[i]).isFormObject())
                {
                    byte[] bytes2 = new byte[bytes.Length - 8];
                    System.Array.Copy(bytes, 0, bytes2, 0, bytes2.Length);
                    bytes = bytes2;
                }

                msoDrawingRecord = new MsoDrawingRecord(bytes);
                outputFile.write(msoDrawingRecord);

                if (i < numImages)
                {
                    // Write anything else the object needs
                    DrawingGroupObject d = (DrawingGroupObject)drawings[i];
                    d.writeAdditionalRecords(outputFile);
                }
                else
                {
                    Chart     chart     = charts[i - numImages];
                    ObjRecord objRecord = chart.getObjRecord();
                    outputFile.write(objRecord);
                    outputFile.write(chart);
                }
            }

            // Write any tail records that need to be written
            foreach (DrawingGroupObject dgo2 in drawings)
            {
                dgo2.writeTailRecords(outputFile);
            }
        }