Exemple #1
0
        /**
         * Returns the index of the format string, used by your cell,
         *  or -1 if none found
         */
        public int GetFormatIndex(CellValueRecordInterface cell)
        {
            ExtendedFormatRecord xfr = (ExtendedFormatRecord)
                                       xfRecords[cell.XFIndex];

            if (xfr == null)
            {
                Console.Error.WriteLine("Cell " + cell.Row + "," + cell.Column + " uses XF with index " + cell.XFIndex + ", but we don't have that");
                return(-1);
            }
            return(xfr.FormatIndex);
        }
        /**
         * Returns the index of the format string, used by your cell,
         *  or -1 if none found
         */

        public int GetFormatIndex(CellValueRecordInterface cell)
        {
            ExtendedFormatRecord xfr = (ExtendedFormatRecord)
                                       xfRecords[cell.XFIndex];

            if (xfr == null)
            {
                logger.Log(POILogger.ERROR, "Cell " + cell.Row + "," + cell.Column + " uses XF with index " + cell.XFIndex + ", but we don't have that");
                return(-1);
            }
            return(xfr.FormatIndex);
        }
        /**
         * Process the record ourselves, but do not
         *  pass it on to the child Listener.
         * @param record
         */

        public void ProcessRecordInternally(Record record)
        {
            if (record is FormatRecord)
            {
                FormatRecord fr = (FormatRecord)record;
                customFormatRecords[fr.IndexCode] = fr;
            }
            else if (record is ExtendedFormatRecord)
            {
                ExtendedFormatRecord xr = (ExtendedFormatRecord)record;
                xfRecords.Add(xr);
            }
        }
        public void TestCloneOnto()
        {
            ExtendedFormatRecord base1 = CreateEFR();

            ExtendedFormatRecord other = new ExtendedFormatRecord();

            other.CloneStyleFrom(base1);

            byte[] recordBytes = other.Serialize();
            Assert.AreEqual(recordBytes.Length - 4, data.Length);
            for (int i = 0; i < data.Length; i++)
            {
                Assert.AreEqual(data[i], recordBytes[i + 4], "At offset " + i);
            }
        }
        public void TestLoad()
        {
            ExtendedFormatRecord record = CreateEFR();

            Assert.AreEqual(0, record.FontIndex);
            Assert.AreEqual(0, record.FormatIndex);
            Assert.AreEqual(0xF5 - 256, record.CellOptions);
            Assert.AreEqual(0x20, record.AlignmentOptions);
            Assert.AreEqual(0, record.IndentionOptions);
            Assert.AreEqual(0, record.BorderOptions);
            Assert.AreEqual(0, record.PaletteOptions);
            Assert.AreEqual(0, record.AdtlPaletteOptions);
            Assert.AreEqual(0x20c0, record.FillPaletteOptions);

            Assert.AreEqual(20 + 4, record.RecordSize);
        }
Exemple #6
0
        public void TestRotation()
        {
            ExtendedFormatRecord record = CreateEFR();

            Assert.AreEqual(0, record.Rotation);
            record.Rotation = ((short)1);
            Assert.AreEqual(1, record.Rotation);
            record.Rotation = ((short)89);
            Assert.AreEqual(89, record.Rotation);
            record.Rotation = ((short)90);
            Assert.AreEqual(90, record.Rotation);
            // internally values below zero are stored differently
            record.Rotation = ((short)-1);
            Assert.AreEqual(255, record.Rotation);
            record.Rotation = ((short)-89);
            Assert.AreEqual(-77, 90 - record.Rotation);
            record.Rotation = ((short)-90);
            Assert.AreEqual(-76, 90 - record.Rotation);
        }
Exemple #7
0
        /**
         * Applying a user-defined style (UDS) is special. Excel does not directly reference user-defined styles, but
         * instead create a 'proxy' ExtendedFormatRecord referencing the UDS as parent.
         *
         * The proceudre to apply a UDS is as follows:
         *
         * 1. search for a ExtendedFormatRecord with parentIndex == style.getIndex()
         *    and xfType ==  ExtendedFormatRecord.XF_CELL.
         * 2. if not found then create a new ExtendedFormatRecord and copy all attributes from the user-defined style
         *    and set the parentIndex to be style.getIndex()
         * 3. return the index of the ExtendedFormatRecord, this will be assigned to the parent cell record
         *
         * @param style  the user style to apply
         *
         * @return  the index of a ExtendedFormatRecord record that will be referenced by the cell
         */
        private short ApplyUserCellStyle(HSSFCellStyle style)
        {
            if (style.UserStyleName == null)
            {
                throw new ArgumentException("Expected user-defined style");
            }

            InternalWorkbook iwb    = book.Workbook;
            short            userXf = -1;
            int numfmt = iwb.NumExFormats;

            for (short i = 0; i < numfmt; i++)
            {
                ExtendedFormatRecord xf = iwb.GetExFormatAt(i);
                if (xf.XFType == ExtendedFormatRecord.XF_CELL && xf.ParentIndex == style.Index)
                {
                    userXf = i;
                    break;
                }
            }
            short styleIndex;

            if (userXf == -1)
            {
                ExtendedFormatRecord xfr = iwb.CreateCellXF();
                xfr.CloneStyleFrom(iwb.GetExFormatAt(style.Index));
                xfr.IndentionOptions = (short)0;
                xfr.XFType           = (ExtendedFormatRecord.XF_CELL);
                xfr.ParentIndex      = (style.Index);
                styleIndex           = (short)numfmt;
            }
            else
            {
                styleIndex = userXf;
            }

            return(styleIndex);
        }
Exemple #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HSSFCellStyle"/> class.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <param name="rec">The record.</param>
 /// <param name="workbook">The workbook.</param>
 public HSSFCellStyle(short index, ExtendedFormatRecord rec, NPOI.HSSF.Model.InternalWorkbook workbook)
 {
     this._workbook = workbook;
     this.index     = index;
     this._format   = rec;
 }
Exemple #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="HSSFCellStyle"/> class.
 /// </summary>
 /// <param name="index">The index.</param>
 /// <param name="rec">The record.</param>
 /// <param name="workbook">The workbook.</param>
 public HSSFCellStyle(short index, ExtendedFormatRecord rec, HSSFWorkbook workbook)
     : this(index, rec, workbook.Workbook)
 {
 }
        public void TestStore()
        {
            //    .fontindex       = 0
            //    .formatindex     = 0
            //    .celloptions     = fffffff5
            //          .Islocked  = true
            //          .Ishidden  = false
            //          .Recordtype= 1
            //          .parentidx = fff
            //    .alignmentoptions= 20
            //          .alignment = 0
            //          .wraptext  = false
            //          .valignment= 2
            //          .justlast  = 0
            //          .rotation  = 0
            //    .indentionoptions= 0
            //          .indent    = 0
            //          .shrinktoft= false
            //          .mergecells= false
            //          .Readngordr= 0
            //          .formatflag= false
            //          .fontflag  = false
            //          .prntalgnmt= false
            //          .borderflag= false
            //          .paternflag= false
            //          .celloption= false
            //    .borderoptns     = 0
            //          .lftln     = 0
            //          .rgtln     = 0
            //          .Topln     = 0
            //          .btmln     = 0
            //    .paleteoptns     = 0
            //          .leftborder= 0
            //          .rghtborder= 0
            //          .diag      = 0
            //    .paleteoptn2     = 0
            //          .Topborder = 0
            //          .botmborder= 0
            //          .adtldiag  = 0
            //          .diaglnstyl= 0
            //          .Fillpattrn= 0
            //    .Fillpaloptn     = 20c0
            //          .foreground= 40
            //          .background= 41

            ExtendedFormatRecord record = new ExtendedFormatRecord();

            record.FontIndex   = (/*setter*/ (short)0);
            record.FormatIndex = (/*setter*/ (short)0);

            record.IsLocked    = (/*setter*/ true);
            record.IsHidden    = (/*setter*/ false);
            record.XFType      = (/*setter*/ (short)1);
            record.ParentIndex = (/*setter*/ (short)0xfff);

            record.VerticalAlignment = (/*setter*/ (short)2);

            record.FillForeground = (/*setter*/ (short)0x40);
            record.FillBackground = (/*setter*/ (short)0x41);

            byte[] recordBytes = record.Serialize();
            Assert.AreEqual(recordBytes.Length - 4, data.Length);
            for (int i = 0; i < data.Length; i++)
            {
                Assert.AreEqual(data[i], recordBytes[i + 4], "At offset " + i);
            }
        }
Exemple #11
0
        /// <summary>
        /// Goes through the Workbook, optimising the fonts by
        /// removing duplicate ones.
        /// For now, only works on fonts used in HSSFCellStyle
        /// and HSSFRichTextString. Any other font uses
        /// (eg charts, pictures) may well end up broken!
        /// This can be a slow operation, especially if you have
        /// lots of cells, cell styles or rich text strings
        /// </summary>
        /// <param name="workbook">The workbook in which to optimise the fonts</param>
        public static void OptimiseFonts(HSSFWorkbook workbook)
        {
            // Where each font has ended up, and if we need to
            //  delete the record for it. Start off with no change
            short[] newPos =
                new short[workbook.Workbook.NumberOfFontRecords + 1];
            bool[] zapRecords = new bool[newPos.Length];
            for (int i = 0; i < newPos.Length; i++)
            {
                newPos[i]     = (short)i;
                zapRecords[i] = false;
            }

            // Get each font record, so we can do deletes
            //  without Getting confused
            FontRecord[] frecs = new FontRecord[newPos.Length];
            for (int i = 0; i < newPos.Length; i++)
            {
                // There is no 4!
                if (i == 4)
                {
                    continue;
                }

                frecs[i] = workbook.Workbook.GetFontRecordAt(i);
            }

            // Loop over each font, seeing if it is the same
            //  as an earlier one. If it is, point users of the
            //  later duplicate copy to the earlier one, and
            //  mark the later one as needing deleting
            // Note - don't change built in fonts (those before 5)
            for (int i = 5; i < newPos.Length; i++)
            {
                // Check this one for being a duplicate
                //  of an earlier one
                int earlierDuplicate = -1;
                for (int j = 0; j < i && earlierDuplicate == -1; j++)
                {
                    if (j == 4)
                    {
                        continue;
                    }

                    FontRecord frCheck = workbook.Workbook.GetFontRecordAt(j);
                    if (frCheck.SameProperties(frecs[i]))
                    {
                        earlierDuplicate = j;
                    }
                }

                // If we got a duplicate, mark it as such
                if (earlierDuplicate != -1)
                {
                    newPos[i]     = (short)earlierDuplicate;
                    zapRecords[i] = true;
                }
            }

            // Update the new positions based on
            //  deletes that have occurred between
            //  the start and them
            // Only need to worry about user fonts
            for (int i = 5; i < newPos.Length; i++)
            {
                // Find the number deleted to that
                //  point, and adjust
                short preDeletePos = newPos[i];
                short newPosition  = preDeletePos;
                for (int j = 0; j < preDeletePos; j++)
                {
                    if (zapRecords[j])
                    {
                        newPosition--;
                    }
                }

                // Update the new position
                newPos[i] = newPosition;
            }

            // Zap the un-needed user font records
            for (int i = 5; i < newPos.Length; i++)
            {
                if (zapRecords[i])
                {
                    workbook.Workbook.RemoveFontRecord(
                        frecs[i]
                        );
                }
            }

            // Tell HSSFWorkbook that it needs to
            //  re-start its HSSFFontCache
            workbook.ResetFontCache();

            // Update the cell styles to point at the
            //  new locations of the fonts
            for (int i = 0; i < workbook.Workbook.NumExFormats; i++)
            {
                ExtendedFormatRecord xfr = workbook.Workbook.GetExFormatAt(i);
                xfr.FontIndex = (
                    newPos[xfr.FontIndex]
                    );
            }

            // Update the rich text strings to point at
            //  the new locations of the fonts
            // Remember that one underlying unicode string
            //  may be shared by multiple RichTextStrings!
            ArrayList doneUnicodeStrings = new ArrayList();

            for (int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
            {
                NPOI.SS.UserModel.ISheet s = workbook.GetSheetAt(sheetNum);
                IEnumerator rIt            = s.GetRowEnumerator();
                while (rIt.MoveNext())
                {
                    HSSFRow     row = (HSSFRow)rIt.Current;
                    IEnumerator cIt = row.GetEnumerator();
                    while (cIt.MoveNext())
                    {
                        ICell cell = (HSSFCell)cIt.Current;
                        if (cell.CellType == NPOI.SS.UserModel.CellType.STRING)
                        {
                            HSSFRichTextString rtr = (HSSFRichTextString)cell.RichStringCellValue;
                            UnicodeString      u   = rtr.RawUnicodeString;

                            // Have we done this string already?
                            if (!doneUnicodeStrings.Contains(u))
                            {
                                // Update for each new position
                                for (short i = 5; i < newPos.Length; i++)
                                {
                                    if (i != newPos[i])
                                    {
                                        u.SwapFontUse(i, newPos[i]);
                                    }
                                }

                                // Mark as done
                                doneUnicodeStrings.Add(u);
                            }
                        }
                    }
                }
            }
        }
Exemple #12
0
        /// <summary>
        /// Goes through the Wokrbook, optimising the cell styles
        /// by removing duplicate ones.
        /// For best results, optimise the fonts via a call to
        /// OptimiseFonts(HSSFWorkbook) first
        /// </summary>
        /// <param name="workbook">The workbook in which to optimise the cell styles</param>
        public static void OptimiseCellStyles(HSSFWorkbook workbook)
        {
            // Where each style has ended up, and if we need to
            //  delete the record for it. Start off with no change
            short[] newPos =
                new short[workbook.Workbook.NumExFormats];
            bool[] zapRecords = new bool[newPos.Length];
            for (int i = 0; i < newPos.Length; i++)
            {
                newPos[i]     = (short)i;
                zapRecords[i] = false;
            }

            // Get each style record, so we can do deletes
            //  without Getting confused
            ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.Length];
            for (int i = 0; i < newPos.Length; i++)
            {
                xfrs[i] = workbook.Workbook.GetExFormatAt(i);
            }

            // Loop over each style, seeing if it is the same
            //  as an earlier one. If it is, point users of the
            //  later duplicate copy to the earlier one, and
            //  mark the later one as needing deleting
            // Only work on user added ones, which come after 20
            for (int i = 21; i < newPos.Length; i++)
            {
                // Check this one for being a duplicate
                //  of an earlier one
                int earlierDuplicate = -1;
                for (int j = 0; j < i && earlierDuplicate == -1; j++)
                {
                    ExtendedFormatRecord xfCheck = workbook.Workbook.GetExFormatAt(j);
                    if (xfCheck.Equals(xfrs[i]))
                    {
                        earlierDuplicate = j;
                    }
                }

                // If we got a duplicate, mark it as such
                if (earlierDuplicate != -1)
                {
                    newPos[i]     = (short)earlierDuplicate;
                    zapRecords[i] = true;
                }
            }

            // Update the new positions based on
            //  deletes that have occurred between
            //  the start and them
            // Only work on user added ones, which come after 20
            for (int i = 21; i < newPos.Length; i++)
            {
                // Find the number deleted to that
                //  point, and adjust
                short preDeletePos = newPos[i];
                short newPosition  = preDeletePos;
                for (int j = 0; j < preDeletePos; j++)
                {
                    if (zapRecords[j])
                    {
                        newPosition--;
                    }
                }

                // Update the new position
                newPos[i] = newPosition;
            }

            // Zap the un-needed user style records
            for (int i = 21; i < newPos.Length; i++)
            {
                if (zapRecords[i])
                {
                    workbook.Workbook.RemoveExFormatRecord(
                        xfrs[i]
                        );
                }
            }

            // Finally, update the cells to point at
            //  their new extended format records
            for (int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
            {
                HSSFSheet   s   = (HSSFSheet)workbook.GetSheetAt(sheetNum);
                IEnumerator rIt = s.GetRowEnumerator();
                while (rIt.MoveNext())
                {
                    HSSFRow     row = (HSSFRow)rIt.Current;
                    IEnumerator cIt = row.GetEnumerator();
                    while (cIt.MoveNext())
                    {
                        ICell cell  = (HSSFCell)cIt.Current;
                        short oldXf = ((HSSFCell)cell).CellValueRecord.XFIndex;
                        NPOI.SS.UserModel.ICellStyle newStyle = workbook.GetCellStyleAt(
                            newPos[oldXf]
                            );
                        cell.CellStyle = (newStyle);
                    }
                }
            }
        }
Exemple #13
0
        /// <summary>
        /// Goes through the Wokrbook, optimising the cell styles
        /// by removing duplicate ones and ones that aren't used.
        /// For best results, optimise the fonts via a call to
        /// OptimiseFonts(HSSFWorkbook) first
        /// </summary>
        /// <param name="workbook">The workbook in which to optimise the cell styles</param>
        public static void OptimiseCellStyles(HSSFWorkbook workbook)
        {
            // Where each style has ended up, and if we need to
            //  delete the record for it. Start off with no change
            short[] newPos =
                new short[workbook.Workbook.NumExFormats];
            bool[] isUsed     = new bool[newPos.Length];
            bool[] zapRecords = new bool[newPos.Length];
            for (int i = 0; i < newPos.Length; i++)
            {
                isUsed[i]     = false;
                newPos[i]     = (short)i;
                zapRecords[i] = false;
            }

            // Get each style record, so we can do deletes
            //  without Getting confused
            ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.Length];
            for (int i = 0; i < newPos.Length; i++)
            {
                xfrs[i] = workbook.Workbook.GetExFormatAt(i);
            }

            // Loop over each style, seeing if it is the same
            //  as an earlier one. If it is, point users of the
            //  later duplicate copy to the earlier one, and
            //  mark the later one as needing deleting
            // Only work on user added ones, which come after 20
            for (int i = 21; i < newPos.Length; i++)
            {
                // Check this one for being a duplicate
                //  of an earlier one
                int earlierDuplicate = -1;
                for (int j = 0; j < i && earlierDuplicate == -1; j++)
                {
                    ExtendedFormatRecord xfCheck = workbook.Workbook.GetExFormatAt(j);
                    if (xfCheck.Equals(xfrs[i]))
                    {
                        earlierDuplicate = j;
                    }
                }

                // If we got a duplicate, mark it as such
                if (earlierDuplicate != -1)
                {
                    newPos[i]     = (short)earlierDuplicate;
                    zapRecords[i] = true;
                }
                // If we got a duplicate, mark the one we're keeping as used
                if (earlierDuplicate != -1)
                {
                    isUsed[earlierDuplicate] = true;
                }
            }
            // Loop over all the cells in the file, and identify any user defined
            //  styles aren't actually being used (don't touch built-in ones)
            for (int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
            {
                HSSFSheet s = (HSSFSheet)workbook.GetSheetAt(sheetNum);
                foreach (IRow row in s)
                {
                    foreach (ICell cellI in row)
                    {
                        HSSFCell cell  = (HSSFCell)cellI;
                        short    oldXf = cell.CellValueRecord.XFIndex;
                        isUsed[oldXf] = true;
                    }
                }
            }
            // Mark any that aren't used as needing zapping
            for (int i = 21; i < isUsed.Length; i++)
            {
                if (!isUsed[i])
                {
                    // Un-used style, can be removed
                    zapRecords[i] = true;
                    newPos[i]     = 0;
                }
            }
            // Update the new positions based on
            //  deletes that have occurred between
            //  the start and them
            // Only work on user added ones, which come after 20
            for (int i = 21; i < newPos.Length; i++)
            {
                // Find the number deleted to that
                //  point, and adjust
                short preDeletePos = newPos[i];
                short newPosition  = preDeletePos;
                for (int j = 0; j < preDeletePos; j++)
                {
                    if (zapRecords[j])
                    {
                        newPosition--;
                    }
                }

                // Update the new position
                newPos[i] = newPosition;
            }

            // Zap the un-needed user style records
            // removing by index, because removing by object may delete
            // styles we did not intend to (the ones that _were_ duplicated and not the duplicates)
            int max     = newPos.Length;
            int removed = 0; // to adjust index after deletion

            for (int i = 21; i < max; i++)
            {
                if (zapRecords[i + removed])
                {
                    workbook.Workbook.RemoveExFormatRecord(i);
                    i--;
                    max--;
                    removed++;
                }
            }

            // Finally, update the cells to point at their new extended format records
            for (int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
            {
                HSSFSheet s = (HSSFSheet)workbook.GetSheetAt(sheetNum);
                //IEnumerator rIt = s.GetRowEnumerator();
                //while (rIt.MoveNext())
                foreach (IRow row in s)
                {
                    //HSSFRow row = (HSSFRow)rIt.Current;
                    //IEnumerator cIt = row.GetEnumerator();
                    //while (cIt.MoveNext())
                    foreach (ICell cell in row)
                    {
                        //ICell cell = (HSSFCell)cIt.Current;
                        short oldXf = ((HSSFCell)cell).CellValueRecord.XFIndex;
                        Npoi.Core.SS.UserModel.ICellStyle newStyle = workbook.GetCellStyleAt(
                            newPos[oldXf]
                            );
                        cell.CellStyle = (newStyle);
                    }
                }
            }
        }