From a2569781c07d6ee03dc6ee3e5d9bcf42b80ed028 Mon Sep 17 00:00:00 2001 From: SayHelloXXXX <550800945@qq.com> Date: Tue, 13 Feb 2018 11:13:16 +0800 Subject: [PATCH 01/38] NPOI.Streaming-pr --- .../Streaming/AutoSizeColumnTracker.cs | 396 +++++++ .../Streaming/GZIPSheetDataWriter.cs | 57 + .../Streaming/Properties/CommentProperty.cs | 31 + .../Streaming/Properties/HyperlinkProperty.cs | 31 + .../Streaming/Properties/Property.cs | 32 + src/NPOI.OOXML/Streaming/SXSSFCell.cs | 791 ++++++++++++++ .../Streaming/SXSSFCreationHelper.cs | 64 ++ .../Streaming/SXSSFEvaluationCell.cs | 131 +++ .../Streaming/SXSSFEvaluationSheet.cs | 63 ++ .../Streaming/SXSSFEvaluationWorkbook.cs | 64 ++ .../Streaming/SXSSFFormulaEvaluator.cs | 130 +++ src/NPOI.OOXML/Streaming/SXSSFRow.cs | 410 ++++++++ src/NPOI.OOXML/Streaming/SXSSFSheet.cs | 989 ++++++++++++++++++ src/NPOI.OOXML/Streaming/SXSSFWorkbook.cs | 736 +++++++++++++ src/NPOI.OOXML/Streaming/SheetDataWriter.cs | 532 ++++++++++ src/NPOI.OOXML/Streaming/Values/BlankValue.cs | 29 + .../Streaming/Values/BooleanFormulaValue.cs | 31 + .../Streaming/Values/BooleanValue.cs | 30 + .../Streaming/Values/ErrorFormulaValue.cs | 31 + src/NPOI.OOXML/Streaming/Values/ErrorValue.cs | 30 + .../Streaming/Values/FormulaValue.cs | 31 + .../Streaming/Values/NumericFormulaValue.cs | 30 + .../Streaming/Values/NumericValue.cs | 29 + .../Streaming/Values/PlainStringValue.cs | 28 + .../Streaming/Values/RichTextValue.cs | 36 + .../Streaming/Values/StringFormulaValue.cs | 31 + .../Streaming/Values/StringValue.cs | 30 + src/NPOI.OOXML/Streaming/Values/Value.cs | 25 + src/NPOI.OOXML/XSSF/UserModel/XSSFCell.cs | 5 + .../XSSF/UserModel/XSSFEvaluationCell.cs | 5 + .../XSSF/UserModel/XSSFEvaluationSheet.cs | 5 + .../XSSF/UserModel/XSSFEvaluationWorkbook.cs | 2 +- .../XSSF/UserModel/XSSFFormulaEvaluator.cs | 6 + .../XSSF/UserModel/XSSFRichTextString.cs | 16 + src/NPOI.OOXML/XSSF/UserModel/XSSFRow.cs | 32 + src/NPOI/HSSF/UserModel/HSSFCell.cs | 5 + src/NPOI/HSSF/UserModel/HSSFRow.cs | 31 + src/NPOI/SS/UserModel/Cell.cs | 2 + src/NPOI/SS/UserModel/Row.cs | 21 + src/NPOI/SS/Util/SheetUtil.cs | 12 + src/NPOI/Util/Character.cs | 6 + 41 files changed, 4995 insertions(+), 1 deletion(-) create mode 100644 src/NPOI.OOXML/Streaming/AutoSizeColumnTracker.cs create mode 100644 src/NPOI.OOXML/Streaming/GZIPSheetDataWriter.cs create mode 100644 src/NPOI.OOXML/Streaming/Properties/CommentProperty.cs create mode 100644 src/NPOI.OOXML/Streaming/Properties/HyperlinkProperty.cs create mode 100644 src/NPOI.OOXML/Streaming/Properties/Property.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFCell.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFCreationHelper.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFEvaluationCell.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFEvaluationSheet.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFEvaluationWorkbook.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFFormulaEvaluator.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFRow.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFSheet.cs create mode 100644 src/NPOI.OOXML/Streaming/SXSSFWorkbook.cs create mode 100644 src/NPOI.OOXML/Streaming/SheetDataWriter.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/BlankValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/BooleanFormulaValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/BooleanValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/ErrorFormulaValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/ErrorValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/FormulaValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/NumericFormulaValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/NumericValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/PlainStringValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/RichTextValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/StringFormulaValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/StringValue.cs create mode 100644 src/NPOI.OOXML/Streaming/Values/Value.cs diff --git a/src/NPOI.OOXML/Streaming/AutoSizeColumnTracker.cs b/src/NPOI.OOXML/Streaming/AutoSizeColumnTracker.cs new file mode 100644 index 0000000..d49e3f4 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/AutoSizeColumnTracker.cs @@ -0,0 +1,396 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using NPOI.SS.UserModel; +using NPOI.SS.Util; + +namespace NPOI.XSSF.Streaming +{ + public class AutoSizeColumnTracker + { + private int defaultCharWidth; + private DataFormatter dataFormatter = new DataFormatter(); + + + /// + /// map of tracked columns, with values containing the best-fit width for the column + /// Using a HashMap instead of a TreeMap because insertion (trackColumn), removal (untrackColumn), and membership (everything) + /// will be called more frequently than getTrackedColumns(). The O(1) cost of insertion, removal, and membership operations + /// outweigh the infrequent O(n*log n) cost of sorting getTrackedColumns(). + /// Memory consumption for a HashMap and TreeMap is about the same + /// + private Dictionary maxColumnWidths = new Dictionary(); + + + // untrackedColumns stores columns have been explicitly untracked so they aren't implicitly re-tracked by trackAllColumns + // Using a HashSet instead of a TreeSet because we don't care about order. + private HashSet untrackedColumns = new HashSet(); + private bool trackAllColumns = false; + + private class ColumnWidthPair + { + private static double withSkipMergedCells; + private static double withUseMergedCells; + + public ColumnWidthPair() : this(-1.0, -1.0) + { + + } + + public ColumnWidthPair(double columnWidthSkipMergedCells, double columnWidthUseMergedCells) + { + withSkipMergedCells = columnWidthSkipMergedCells; + withUseMergedCells = columnWidthUseMergedCells; + } + + /** + * Gets the current best-fit column width for the provided settings + * + * @param useMergedCells true if merged cells are considered into the best-fit column width calculation + * @return best fit column width, measured in default character widths. + */ + public double getMaxColumnWidth(bool useMergedCells) + { + return useMergedCells ? withUseMergedCells : withSkipMergedCells; + } + + /** + * Sets the best-fit column width to the maximum of the current width and the provided width + * + * @param unmergedWidth the best-fit column width calculated with useMergedCells=False + * @param mergedWidth the best-fit column width calculated with useMergedCells=True + */ + public void setMaxColumnWidths(double unmergedWidth, double mergedWidth) + { + withUseMergedCells = Math.Max(withUseMergedCells, mergedWidth); + withSkipMergedCells = Math.Max(withUseMergedCells, unmergedWidth); + } + } + + /** + * AutoSizeColumnTracker constructor. Holds no reference to sheet + * + * @param sheet the sheet associated with this auto-size column tracker + * @since 3.14beta1 + */ + public AutoSizeColumnTracker(ISheet sheet) + { + // If sheet needs to be saved, use a java.lang.ref.WeakReference to avoid garbage collector gridlock. + defaultCharWidth = SheetUtil.getDefaultCharWidth(sheet.Workbook); + } + + /** + * Get the currently tracked columns, naturally ordered. + * Note if all columns are tracked, this will only return the columns that have been explicitly or implicitly tracked, + * which is probably only columns containing 1 or more non-blank values + * + * @return a set of the indices of all tracked columns + * @since 3.14beta1 + */ + public SortedSet getTrackedColumns() + { + throw new NotImplementedException(); + //var sorted = new ColumnHelper.TreeSet(maxColumnWidths.Keys); + //return Collection.unmodifiableSortedSet(sorted); + } + + /** + * Returns true if column is currently tracked for auto-sizing. + * + * @param column the index of the column to check + * @return true if column is tracked + * @since 3.14beta1 + */ + public bool isColumnTracked(int column) + { + return trackAllColumns|| maxColumnWidths.ContainsKey(column); + } + + /** + * Returns true if all columns are implicitly tracked. + * + * @return true if all columns are implicitly tracked + * @since 3.14beta1 + */ + public bool isAllColumnsTracked() + { + return trackAllColumns; + } + + /** + * Tracks all non-blank columns + * Allows columns that have been explicitly untracked to be tracked + * @since 3.14beta1 + */ + public void TrackAllColumns() + { + trackAllColumns = true; + untrackedColumns.Clear(); + } + + /** + * Untrack all columns that were previously tracked for auto-sizing. + * All best-fit column widths are forgotten. + * @since 3.14beta1 + */ + public void untrackAllColumns() + { + trackAllColumns = false; + maxColumnWidths.Clear(); + untrackedColumns.Clear(); + } + + /** + * Marks multiple columns for inclusion in auto-size column tracking. + * Note this has undefined behavior if columns are tracked after one or more rows are written to the sheet. + * Any column in columns that are already tracked are ignored by this call. + * + * @param columns the indices of the columns to track + * @since 3.14beta1 + */ + public void trackColumns(Collection columns) + { + foreach ( int column in columns) + { + trackColumn(column); + } + } + + /** + * Marks a column for inclusion in auto-size column tracking. + * Note this has undefined behavior if a column is tracked after one or more rows are written to the sheet. + * If column is already tracked, this call does nothing. + * + * @param column the index of the column to track for auto-sizing + * @return if column is already tracked, the call does nothing and returns false + * @since 3.14beta1 + */ + public bool trackColumn(int column) + { + untrackedColumns.Remove(column); + if (!maxColumnWidths.ContainsKey(column)) + { + maxColumnWidths.Add(column, new ColumnWidthPair()); + return true; + } + return false; + } + + /** + * Implicitly track a column if it has not been explicitly untracked + * If it has been explicitly untracked, this call does nothing and returns false. + * Otherwise return true + * + * @param column the column to implicitly track + * @return false if column has been explicitly untracked, otherwise return true + */ + private bool implicitlyTrackColumn(int column) + { + if (!untrackedColumns.Contains(column)) + { + trackColumn(column); + return true; + } + return false; + } + + /** + * Removes columns that were previously marked for inclusion in auto-size column tracking. + * When a column is untracked, the best-fit width is forgotten. + * Any column in columns that is not tracked will be ignored by this call. + * + * @param columns the indices of the columns to track for auto-sizing + * @return true if one or more columns were untracked as a result of this call + * @since 3.14beta1 + */ + public bool UntrackColumns(Collection columns) + { + bool result = false; + foreach (var col in columns) + { + untrackedColumns.Add(col); + if (maxColumnWidths.ContainsKey(col)) + { + result= maxColumnWidths.Remove(col); + } + } + + return result; + } + + /** + * Removes a column that was previously marked for inclusion in auto-size column tracking. + * When a column is untracked, the best-fit width is forgotten. + * If column is not tracked, it will be ignored by this call. + * + * @param column the index of the column to track for auto-sizing + * @return true if column was tracked prior this call, false if no action was taken + * @since 3.14beta1 + */ + public bool untrackColumn(int column) + { + var result = false; + if (maxColumnWidths.ContainsKey(column)) + { + untrackedColumns.Add(column); + result = maxColumnWidths.Remove(column); + } + untrackedColumns.Add(column); + return result; + } + + /** + * Get the best-fit width of a tracked column + * + * @param column the index of the column to get the current best-fit width of + * @param useMergedCells true if merged cells should be considered when computing the best-fit width + * @return best-fit column width, measured in number of characters + * @throws IllegalStateException if column is not tracked and trackAllColumns is false + * @since 3.14beta1 + */ + public int getBestFitColumnWidth(int column, bool useMergedCells) + { + if (!maxColumnWidths.ContainsKey(column)) + { + // if column is not tracked, implicitly track the column if trackAllColumns is True and column has not been explicitly untracked + if (trackAllColumns) + { + if (!implicitlyTrackColumn(column)) + { + var reason = new InvalidOperationException( + "Column was explicitly untracked after trackAllColumns() was called."); + throw new InvalidOperationException( + "Cannot get best fit column width on explicitly untracked column " + column + ". " + + "Either explicitly track the column or track all columns.",reason); + } + } + else + { + var reason = new InvalidOperationException( + "Column was never explicitly tracked and isAllColumnsTracked() is false " + + "(trackAllColumns() was never called or untrackAllColumns() was called after trackAllColumns() was called)."); + throw new InvalidOperationException( + "Cannot get best fit column width on untracked column " + column + ". " + + "Either explicitly track the column or track all columns.", reason); + } + } + double width = maxColumnWidths[column].getMaxColumnWidth(useMergedCells); + return (int)(256 * width); + } + + + + /** + * Calculate the best fit width for each tracked column in row + * + * @param row the row to get the cells + * @since 3.14beta1 + */ + + public void UpdateColumnWidths(IRow row) + { + // track new columns + ImplicitlyTrackColumnsInRow(row); + + // update the widths + // for-loop over the shorter of the number of cells in the row and the number of tracked columns + // these two for-loops should do the same thing + if (maxColumnWidths.Count < row.PhysicalNumberOfCells) + { + // loop over the tracked columns, because there are fewer tracked columns than cells in this row + foreach (var e in maxColumnWidths) + { + int column = e.Key; + ICell cell = row.GetCell(column); //is MissingCellPolicy=Row.RETURN_NULL_AND_BLANK needed? + + // FIXME: if cell belongs to a merged region, some of the merged region may have fallen outside of the random access window + // In this case, getting the column width may result in an error. Need to gracefully handle this. + + // FIXME: Most cells are not merged, so calling getCellWidth twice re-computes the same value twice. + // Need to rewrite this to avoid unnecessary computation if this proves to be a performance bottleneck. + + if (cell != null) + { + ColumnWidthPair pair = e.Value; + UpdateColumnWidth(cell, pair); + } + } + } + else + { + // loop over the cells in this row, because there are fewer cells in this row than tracked columns + foreach (var cell in row) + { + int column = cell.ColumnIndex; + + // FIXME: if cell belongs to a merged region, some of the merged region may have fallen outside of the random access window + // In this case, getting the column width may result in an error. Need to gracefully handle this. + + // FIXME: Most cells are not merged, so calling getCellWidth twice re-computes the same value twice. + // Need to rewrite this to avoid unnecessary computation if this proves to be a performance bottleneck. + + if (maxColumnWidths.ContainsKey(column)) + { + ColumnWidthPair pair = maxColumnWidths[column]; + UpdateColumnWidth(cell, pair); + } + } + } + } + + /** + * Helper for {@link #updateColumnWidths(Row)}. + * Implicitly track the columns corresponding to the cells in row. + * If all columns in the row are already tracked, this call does nothing. + * Explicitly untracked columns will not be tracked. + * + * @param row the row containing cells to implicitly track the columns + * @since 3.14beta1 + */ + private void ImplicitlyTrackColumnsInRow(IRow row) + { + // track new columns + if (trackAllColumns) + { + // if column is not tracked, implicitly track the column if trackAllColumns is True and column has not been explicitly untracked + foreach (var cell in row) + { + int column = cell.ColumnIndex; + implicitlyTrackColumn(column); + } + } + } + + /** + * Helper for {@link #updateColumnWidths(Row)}. + * + * @param cell the cell to compute the best fit width on + * @param pair the column width pair to update + * @since 3.14beta1 + */ + private void UpdateColumnWidth(ICell cell, ColumnWidthPair pair) + { + double unmergedWidth = SheetUtil.GetCellWidth(cell, defaultCharWidth, dataFormatter, false); + double mergedWidth = SheetUtil.GetCellWidth(cell, defaultCharWidth, dataFormatter, true); + pair.setMaxColumnWidths(unmergedWidth, mergedWidth); + } + } + + +} diff --git a/src/NPOI.OOXML/Streaming/GZIPSheetDataWriter.cs b/src/NPOI.OOXML/Streaming/GZIPSheetDataWriter.cs new file mode 100644 index 0000000..8ad483c --- /dev/null +++ b/src/NPOI.OOXML/Streaming/GZIPSheetDataWriter.cs @@ -0,0 +1,57 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System.IO; +using ICSharpCode.SharpZipLib.GZip; +using NPOI.Util; +using NPOI.XSSF.Model; + +namespace NPOI.XSSF.Streaming +{ + public class GZIPSheetDataWriter : SheetDataWriter + { + public GZIPSheetDataWriter() : base() + { + + } + + /** + * @param sharedStringsTable the shared strings table, or null if inline text is used + */ + public GZIPSheetDataWriter(SharedStringsTable sharedStringsTable) : base(sharedStringsTable) + { + } + + /** + * @return temp file to write sheet data + */ + + public override FileInfo CreateTempFile() + { + return TempFile.CreateTempFile("poi-sxssf-sheet-xml", ".gz"); + } + + protected override Stream DecorateInputStream(Stream fis) + { + return new GZipInputStream(fis); + } + + protected override Stream DecorateOutputStream(Stream fos) + { + return new GZipOutputStream(fos); + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Properties/CommentProperty.cs b/src/NPOI.OOXML/Streaming/Properties/CommentProperty.cs new file mode 100644 index 0000000..9f049cf --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Properties/CommentProperty.cs @@ -0,0 +1,31 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +namespace NPOI.XSSF.Streaming.Properties +{ + public class CommentProperty : Property + { + public CommentProperty(object value) : base(value) + { + + } + + public override int GetType() + { + return COMMENT; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Properties/HyperlinkProperty.cs b/src/NPOI.OOXML/Streaming/Properties/HyperlinkProperty.cs new file mode 100644 index 0000000..88b0bf9 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Properties/HyperlinkProperty.cs @@ -0,0 +1,31 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +namespace NPOI.XSSF.Streaming.Properties +{ + public class HyperlinkProperty : Property + { + public HyperlinkProperty(object value) : base(value) + { + + } + + public override int GetType() + { + return HYPERLINK; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Properties/Property.cs b/src/NPOI.OOXML/Streaming/Properties/Property.cs new file mode 100644 index 0000000..e9399b5 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Properties/Property.cs @@ -0,0 +1,32 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +namespace NPOI.XSSF.Streaming.Properties +{ + public abstract class Property + { + public const int COMMENT = 1; + public const int HYPERLINK = 2; + public object _value; + public Property _next; + + protected Property(object value) + { + _value = value; + } + public abstract int GetType(); + } +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFCell.cs b/src/NPOI.OOXML/Streaming/SXSSFCell.cs new file mode 100644 index 0000000..e37b69e --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFCell.cs @@ -0,0 +1,791 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using NPOI.SS; +using NPOI.SS.UserModel; +using NPOI.SS.Util; +using NPOI.Util; +using NPOI.XSSF.Streaming.Properties; +using NPOI.XSSF.Streaming.Values; +using NPOI.XSSF.UserModel; +using Value = NPOI.XSSF.Streaming.Values.Value; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFCell : ICell + { + private static POILogger logger = POILogFactory.GetLogger(typeof(SXSSFCell)); + + private SXSSFRow _row; + private Value _value; + private ICellStyle _style; + private Property _firstProperty; + + public SXSSFCell(SXSSFRow row, CellType cellType) + { + _row = row; + SetType(cellType); + } + + public CellRangeAddress ArrayFormulaRange + { + get + { + throw new NotImplementedException(); + } + } + + public bool BooleanCellValue + { + get + { + CellType cellType = _value.GetType(); + switch (cellType) + { + case CellType.Blank: + return false; + case CellType.Formula: + { + FormulaValue fv = (FormulaValue)_value; + if (fv.GetFormulaType() != CellType.Boolean) + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.Boolean, CellType.Formula, false)); + return ((BooleanFormulaValue)_value).PreEvaluatedValue; + } + case CellType.Boolean: + { + return ((BooleanValue)_value).Value; + } + default: + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.Boolean, cellType, false)); + } + } + } + + private string BuildTypeMismatchMessage(CellType expectedTypeCode, CellType actualTypeCode, + bool isFormulaCell) + { + return string.Format("Cannot get a {0} value from a {1} {2} cell", expectedTypeCode, actualTypeCode,(isFormulaCell ? "formula " : "")); + } + + public CellType CachedFormulaResultType + { + get { return GetCachedFormulaResultTypeEnum(); } + } + + public CellType GetCachedFormulaResultTypeEnum() + { + if (_value.GetType() != CellType.Formula) + { + throw new InvalidOperationException("Only formula cells have cached results"); + } + + return ((FormulaValue)_value).GetFormulaType(); + } + + public IComment CellComment + { + get + { + return (IComment)GetPropertyValue(Property.COMMENT); + } + + set + { + SetProperty(Property.COMMENT, value); + } + } + + public string CellFormula + { + get + { + if (_value.GetType() != CellType.Formula) + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.Formula, _value.GetType(), false)); + return ((FormulaValue) _value).Value; + } + + set + { + if (value == null) + { + SetType(CellType.Blank); + return; + } + + EnsureFormulaType(ComputeTypeFromFormula(value)); + ((FormulaValue)_value).Value = value; + } + } + + public ICellStyle CellStyle + { + get + { + if (_style == null) + { + SXSSFWorkbook wb = (SXSSFWorkbook)Row.Sheet.Workbook; + return wb.GetCellStyleAt(0); + } + else + { + return _style; + } + } + + set + { + _style = value; + } + } + + public CellType CellType + { + get { return _value.GetType(); } + } + + public int ColumnIndex + { + get + { + return _row.getCellIndex(this); + } + } + + public DateTime DateCellValue + { + get + { + CellType cellType = _value.GetType(); + if (cellType == CellType.Blank) + { + return new DateTime(); + } + + double value = NumericCellValue; + bool date1904= ((XSSFWorkbook)Sheet.Workbook).IsDate1904(); + return DateUtil.GetJavaDate(value, date1904); + } + } + + public byte ErrorCellValue + { + get + { + CellType cellType = _value.GetType(); + switch (cellType) + { + case CellType.Blank: + return 0; + case CellType.Formula: + { + FormulaValue fv = (FormulaValue)_value; + if (fv.GetFormulaType() != CellType.Error) + new InvalidOperationException(BuildTypeMismatchMessage(CellType.Error, CellType.Formula, false)); + return ((ErrorFormulaValue)_value).PreEvaluatedValue; + } + case CellType.Error: + { + return ((ErrorValue)_value).Value; + } + default: + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.Error, cellType, false)); + } + } + } + + public IHyperlink Hyperlink + { + get + { + return (IHyperlink)GetPropertyValue(Property.HYPERLINK); + } + + set + { + throw new NotImplementedException(); + //if (Hyperlink == null) + //{ + // RemoveHyperlink(); + // return; + //} + + //SetProperty(Property.HYPERLINK, Hyperlink); + + //XSSFHyperlink xssfobj = (XSSFHyperlink)Hyperlink; + //// Assign to us + //CellReference reference = new CellReference(RowIndex, ColumnIndex); + //xssfobj.GetCTHyperlink().@ref = reference.FormatAsString(); + + //// Add to the lists + //Sheet._sh.addHyperlink(xssfobj); + } + } + + public bool IsMergedCell + { + get + { + throw new NotImplementedException(); + } + } + + public bool IsPartOfArrayFormulaGroup + { + get + { + return false; + throw new NotImplementedException(); + } + } + + public double NumericCellValue + { + get + { + CellType cellType = _value.GetType(); + switch (cellType) + { + case CellType.Blank: + return 0.0; + case CellType.Formula: + { + FormulaValue fv = (FormulaValue)_value; + if (fv.GetFormulaType() != CellType.Numeric) + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.Numeric, CellType.Formula, false)); + return ((NumericFormulaValue)_value).PreEvaluatedValue; + } + case CellType.Numeric: + return ((NumericValue) _value).Value; + default: + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.Numeric, cellType, false)); + } + } + } + + public IRichTextString RichStringCellValue + { + get + { + CellType cellType = _value.GetType(); + if (cellType != CellType.String) + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.String, cellType, false)); + + StringValue sval = (StringValue)_value; + if (sval.IsRichText()) + return ((RichTextValue) _value).Value; + else + { + string plainText = StringCellValue; + return Sheet.Workbook.GetCreationHelper().CreateRichTextString(plainText); + } + } + } + + public IRow Row + { + get { return _row; } + } + + public int RowIndex + { + get + { + return _row.RowNum; + } + } + + public ISheet Sheet + { + get + { + return _row.Sheet; + } + } + + public string StringCellValue + { + get + { + CellType cellType = _value.GetType(); + switch (cellType) + { + case CellType.Blank: + return ""; + case CellType.Formula: + { + FormulaValue fv = (FormulaValue)_value; + if (fv.GetFormulaType() != CellType.String) + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.String, CellType.Formula, false)); + return ((StringFormulaValue)_value).PreEvaluatedValue; + } + case CellType.String: + { + if (((StringValue) _value).IsRichText()) + return ((RichTextValue) _value).Value.String; + else + return ((PlainStringValue) _value).Value; + } + default: + throw new InvalidOperationException(BuildTypeMismatchMessage(CellType.String, cellType, false)); + } + + } + } + + public ICell CopyCellTo(int targetIndex) + { + throw new NotImplementedException(); + } + + public void RemoveCellComment() + { + RemoveProperty(Property.COMMENT); + } + + //TODO: implement correctly + public void RemoveHyperlink() + { + throw new NotImplementedException(); + //RemoveProperty(Property.HYPERLINK); + + //Sheet.RemoveHyperlink(getRowIndex(), getColumnIndex()); + } + + public void SetAsActiveCell() + { + //TODO: + throw new NotImplementedException(); + // Sheet.SetActiveCell(CellAddress); + } + + public void SetCellErrorValue(byte value) + { + //ensure type garuntees that the type is error so the if condition is never true. + EnsureType(CellType.Error); + if (_value.GetType() == CellType.Formula) + ((ErrorFormulaValue)_value).PreEvaluatedValue = value; + else + ((ErrorValue)_value).Value = value; + } + + public void SetCellFormula(string formula) + { + if (formula == null) + { + SetType(CellType.Blank); + return; + } + + EnsureFormulaType(ComputeTypeFromFormula(formula)); + ((FormulaValue)_value).Value = formula; + } + + //TODO: not implemented correctly in poi 3.16 beta + private CellType ComputeTypeFromFormula(String formula) + { + return CellType.Numeric; + } + + public void SetCellType(CellType cellType) + { + EnsureType(cellType); + } + + public void SetCellValue(string value) + { + if (value != null) + { + EnsureTypeOrFormulaType(CellType.String); + + if (value.Length > SpreadsheetVersion.EXCEL2007.MaxTextLength) + { + throw new InvalidOperationException("The maximum length of cell contents (text) is 32,767 characters"); + } + + if (_value.GetType() == CellType.Formula) + if (_value is NumericFormulaValue) { + ((NumericFormulaValue)_value).PreEvaluatedValue = Double.Parse(value); + } else { + ((StringFormulaValue)_value).Value = value; + } + else + ((PlainStringValue)_value).Value = value; + } + else + { + SetCellType(CellType.Blank); + } + } + + public void SetCellValue(bool value) + { + EnsureTypeOrFormulaType(CellType.Boolean); + if (_value.GetType() == CellType.Formula) + ((BooleanFormulaValue)_value).PreEvaluatedValue = value; + else + ((BooleanValue)_value).Value = value; + } + + public void SetCellValue(IRichTextString value) + { + XSSFRichTextString xvalue = (XSSFRichTextString)value; + + if (xvalue != null && xvalue.String != null) + { + EnsureRichTextStringType(); + + if (xvalue.Length > SpreadsheetVersion.EXCEL2007.MaxTextLength) + { + throw new InvalidOperationException("The maximum length of cell contents (text) is 32,767 characters"); + } + + if (xvalue.HasFormatting()) + logger.Log(POILogger.WARN, "SXSSF doesn't support Shared Strings, rich text formatting information has be lost"); + + ((RichTextValue)_value).Value = xvalue; + } + else + { + SetCellType(CellType.Blank); + } + } + + public void SetCellValue(DateTime? value) + { + if (value == null) + { + SetCellType(CellType.Blank); + return; + } + + bool date1904 = ((XSSFWorkbook)Sheet.Workbook).IsDate1904(); + SetCellValue(DateUtil.GetExcelDate(value.Value, date1904)); + } + + public void SetCellValue(double value) + { + if (Double.IsInfinity(value)) + { + // Excel does not support positive/negative infinities, + // rather, it gives a #DIV/0! error in these cases. + SetCellErrorValue(FormulaError.DIV0.Code); + } + else if (Double.IsNaN(value)) + { + SetCellErrorValue(FormulaError.NUM.Code); + } + else + { + EnsureTypeOrFormulaType(CellType.Numeric); + if (_value.GetType() == CellType.Formula) + ((NumericFormulaValue)_value).PreEvaluatedValue = value; + else + ((NumericValue)_value).Value = value; + } + } + + private void RemoveProperty(int type) + { + Property current = _firstProperty; + Property previous = null; + while (current != null && current.GetType() != type) + { + previous = current; + current = current._next; + } + if (current != null) + { + if (previous != null) + { + previous._next = current._next; + } + else + { + _firstProperty = current._next; + } + } + } + + private void SetProperty(int type, object value) + { + Property current = _firstProperty; + Property previous = null; + while (current != null && current.GetType() != type) + { + previous = current; + current = current._next; + } + if (current != null) + { + current._value = value; + } + else + { + switch (type) + { + case Property.COMMENT: + { + current = new CommentProperty(value); + break; + } + case Property.HYPERLINK: + { + current = new HyperlinkProperty(value); + break; + } + default: + { + throw new InvalidOperationException("Invalid type: " + type); + } + } + if (previous != null) + { + previous._next = current; + } + else + { + _firstProperty = current; + } + } + } + + private object GetPropertyValue(int type) + { + return getPropertyValue(type, null); + } + + private object getPropertyValue(int type, string defaultValue) + { + Property current = _firstProperty; + while (current != null && current.GetType() != type) current = current._next; + return current == null ? defaultValue : current._value; + } + + private void EnsurePlainStringType() + { + if (_value.GetType() != CellType.String + || ((StringValue)_value).IsRichText()) + _value = new PlainStringValue(); + } + + private void EnsureRichTextStringType() + { + if (_value.GetType() != CellType.String + || !((StringValue)_value).IsRichText()) + _value = new RichTextValue(); + } + + private void EnsureType(CellType type) + { + if (_value.GetType() != type) + SetType(type); + } + + private void EnsureFormulaType(CellType type) + { + if (_value.GetType() != CellType.Formula + || ((FormulaValue)_value).GetFormulaType() != type) + setFormulaType(type); + } + /* + * Sets the cell type to type if it is different + */ + + private void EnsureTypeOrFormulaType(CellType type) + { + if (_value.GetType() == type) + { + if (type == CellType.String && ((StringValue)_value).IsRichText()) + SetType(CellType.String); + return; + } + if (_value.GetType() == CellType.Formula) + { + if (((FormulaValue)_value).GetFormulaType() == type) + return; + setFormulaType(type); // once a formula, always a formula + return; + } + SetType(type); + } + + /*package*/ + private void SetType(CellType type) + { + switch (type) + { + case CellType.Numeric: + { + _value = new NumericValue(); + break; + } + case CellType.String: + { + PlainStringValue sval = new PlainStringValue(); + if (_value != null) + { + // if a cell is not blank then convert the old value to string + String str = convertCellValueToString(); + sval.Value = str; + } + _value = sval; + break; + } + case CellType.Formula: + { + _value = new NumericFormulaValue(); + break; + } + case CellType.Blank: + { + _value = new BlankValue(); + break; + } + case CellType.Boolean: + { + BooleanValue bval = new BooleanValue(); + if (_value != null) + { + // if a cell is not blank then convert the old value to string + bool val = convertCellValueToBoolean(); + bval.Value = val; + } + _value = bval; + break; + } + case CellType.Error: + { + _value = new ErrorValue(); + break; + } + default: + { + throw new InvalidOperationException("Illegal type " + type); + } + } + } + + private void setFormulaType(CellType type) + { + Value prevValue = _value; + switch (type) + { + case CellType.Numeric: + { + _value = new NumericFormulaValue(); + break; + } + case CellType.String: + { + _value = new StringFormulaValue(); + break; + } + case CellType.Boolean: + { + _value = new BooleanFormulaValue(); + break; + } + case CellType.Error: + { + _value = new ErrorFormulaValue(); + break; + } + default: + { + throw new InvalidOperationException("Illegal type " + type); + } + } + + // if we had a Formula before, we should copy over the _value of the formula + if (prevValue is FormulaValue) + { + ((FormulaValue)_value).Value = ((FormulaValue)prevValue).Value; + } + } + + //COPIED FROM https://svn.apache.org/repos/asf/poi/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java since the functions are declared private there + private bool convertCellValueToBoolean() + { + CellType cellType = _value.GetType(); + + if (cellType == CellType.Formula) + { + cellType = GetCachedFormulaResultTypeEnum(); + } + + switch (cellType) + { + case CellType.Boolean: + return BooleanCellValue; + case CellType.String: + + String text = StringCellValue; + return Boolean.Parse(text); + case CellType.Numeric: + return NumericCellValue != 0; + case CellType.Error: + case CellType.Blank: + return false; + default: throw new RuntimeException("Unexpected cell type (" + cellType + ")"); + } + + } + private String convertCellValueToString() + { + CellType cellType = _value.GetType(); + return convertCellValueToString(cellType); + } + private String convertCellValueToString(CellType cellType) + { + switch (cellType) + { + case CellType.Blank: + return ""; + case CellType.Boolean: + return BooleanCellValue ? "TRUE" : "FALSE"; + case CellType.String: + return StringCellValue; + case CellType.Numeric: + return NumericCellValue.ToString(); + case CellType.Error: + byte errVal = ErrorCellValue; + return FormulaError.ForInt(errVal).ToString(); + + case CellType.Formula: + if (_value != null) + { + FormulaValue fv = (FormulaValue)_value; + if (fv.GetFormulaType() != CellType.Formula) + { + return convertCellValueToString(fv.GetFormulaType()); + } + } + return ""; + default: + throw new InvalidOperationException("Unexpected cell type (" + cellType + ")"); + } + } + + //END OF COPIED CODE + + + public void SetCellValue(DateTime value) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFCreationHelper.cs b/src/NPOI.OOXML/Streaming/SXSSFCreationHelper.cs new file mode 100644 index 0000000..5315638 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFCreationHelper.cs @@ -0,0 +1,64 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; +using NPOI.Util; +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFCreationHelper : ICreationHelper + { + private static POILogger logger = POILogFactory.GetLogger(typeof(SXSSFCreationHelper)); + + private SXSSFWorkbook wb; + private XSSFCreationHelper helper; + + public SXSSFCreationHelper(SXSSFWorkbook workbook) + { + this.helper = new XSSFCreationHelper(workbook.XssfWorkbook); + this.wb = workbook; + } + + public IClientAnchor CreateClientAnchor() + { + return helper.CreateClientAnchor(); + } + + public IDataFormat CreateDataFormat() + { + return helper.CreateDataFormat(); + } + + public IFormulaEvaluator CreateFormulaEvaluator() + { + return new SXSSFFormulaEvaluator(wb); + } + + public IHyperlink CreateHyperlink(HyperlinkType type) + { + return helper.CreateHyperlink(type); + } + + public IRichTextString CreateRichTextString(string text) + { + logger.Log(POILogger.INFO, "SXSSF doesn't support Rich Text Strings, any formatting information will be lost"); + return new XSSFRichTextString(text); + } + + //TODO: missing methods CreateExtendedColor() + } +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFEvaluationCell.cs b/src/NPOI.OOXML/Streaming/SXSSFEvaluationCell.cs new file mode 100644 index 0000000..a49cb88 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFEvaluationCell.cs @@ -0,0 +1,131 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using NPOI.SS.UserModel; +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFEvaluationCell : XSSFEvaluationCell + { + private SXSSFEvaluationSheet _evalSheet; + private SXSSFCell _cell; + + public SXSSFEvaluationCell(SXSSFCell cell, SXSSFEvaluationSheet evaluationSheet) + { + _cell = cell; + _evalSheet = evaluationSheet; + } + + public SXSSFEvaluationCell(SXSSFCell cell): this(cell, null/*new SXSSFEvaluationSheet(cell.Sheet)*/) + { + throw new NotImplementedException(); + } + + + public Object getIdentityKey() + { + // save memory by just using the cell itself as the identity key + // Note - this assumes SXSSFCell has not overridden hashCode and equals + return _cell; + } + + public SXSSFCell getSXSSFCell() + { + return _cell; + } + + public bool getBooleanCellValue() + { + return _cell.BooleanCellValue; + } + /** + * Will return {@link CellType} in a future version of POI. + * For forwards compatibility, do not hard-code cell type literals in your code. + * + * @return cell type + */ + + public int getCellType() + { + return (int)_cell.CellType; + } + /** + * @since POI 3.15 beta 3 + * @deprecated POI 3.15 beta 3. + * Will be deleted when we make the CellType enum transition. See bug 59791. + */ + //(since= "POI 3.15 beta 3") + + public CellType getCellTypeEnum() + { + return _cell.CellType; + } + + public int getColumnIndex() + { + return _cell.ColumnIndex; + } + + public int getErrorCellValue() + { + return _cell.ErrorCellValue; + } + + public double getNumericCellValue() + { + return _cell.NumericCellValue; + } + + public int getRowIndex() + { + return _cell.RowIndex; + } + + public SXSSFEvaluationSheet getSheet() + { + return _evalSheet; + } + + public String getStringCellValue() + { + return _cell.RichStringCellValue.String; + } + /** + * Will return {@link CellType} in a future version of POI. + * For forwards compatibility, do not hard-code cell type literals in your code. + * + * @return cell type of cached formula result + */ + + public int getCachedFormulaResultType() + { + return (int)_cell.CachedFormulaResultType; + } + /** + * @since POI 3.15 beta 3 + * @deprecated POI 3.15 beta 3. + * Will be deleted when we make the CellType enum transition. See bug 59791. + */ + //@Internal(since= "POI 3.15 beta 3") + + public CellType getCachedFormulaResultTypeEnum() + { + return _cell.GetCachedFormulaResultTypeEnum(); + } +} +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFEvaluationSheet.cs b/src/NPOI.OOXML/Streaming/SXSSFEvaluationSheet.cs new file mode 100644 index 0000000..f3f1041 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFEvaluationSheet.cs @@ -0,0 +1,63 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFEvaluationSheet : XSSFEvaluationSheet + { + private SXSSFSheet _xs; + + public SXSSFEvaluationSheet(SXSSFSheet sheet) + { + _xs = sheet; + } + + public SXSSFSheet getSXSSFSheet() + { + return _xs; + } + + public SXSSFEvaluationCell getCell(int rowIndex, int columnIndex) + { + SXSSFRow row = _xs._rows[rowIndex]; + if (row == null) + { + if (rowIndex <= _xs.lastFlushedRowNumber) + { + throw new RowFlushedException(rowIndex); + } + return null; + } + SXSSFCell cell = (SXSSFCell)row.Cells[columnIndex]; + if (cell == null) + { + return null; + } + return new SXSSFEvaluationCell(cell, this); + } + + /* (non-JavaDoc), inherit JavaDoc from EvaluationSheet + * @since POI 3.15 beta 3 + */ + + public void clearAllCachedResultValues() + { + // nothing to do + } + } +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFEvaluationWorkbook.cs b/src/NPOI.OOXML/Streaming/SXSSFEvaluationWorkbook.cs new file mode 100644 index 0000000..642ca38 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFEvaluationWorkbook.cs @@ -0,0 +1,64 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using NPOI.SS.Formula; +using NPOI.SS.Formula.PTG; +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFEvaluationWorkbook : XSSFEvaluationWorkbook + { + private SXSSFWorkbook _uBook; + + public static SXSSFEvaluationWorkbook create(SXSSFWorkbook book) + { + if (book == null) + { + return null; + } + return new SXSSFEvaluationWorkbook(book); + } + + private SXSSFEvaluationWorkbook(SXSSFWorkbook book) : base(book.XssfWorkbook) + { + _uBook = book; + } + + + public int getSheetIndex(SXSSFEvaluationSheet evalSheet) + { + SXSSFSheet sheet = ((SXSSFEvaluationSheet)evalSheet).getSXSSFSheet(); + return _uBook.GetSheetIndex(sheet); + } + + + public SXSSFEvaluationSheet getSheet(int sheetIndex) + { + throw new NotImplementedException(); + //return new SXSSFEvaluationSheet(_uBook.GetSheetAt(sheetIndex)); + } + + + public Ptg[] getFormulaTokens(SXSSFEvaluationCell evalCell) + { + SXSSFCell cell = ((SXSSFEvaluationCell)evalCell).getSXSSFCell(); + return FormulaParser.Parse(cell.CellFormula, this, FormulaType.Cell, _uBook.GetSheetIndex(cell.Sheet)); + } +} + +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFFormulaEvaluator.cs b/src/NPOI.OOXML/Streaming/SXSSFFormulaEvaluator.cs new file mode 100644 index 0000000..88922e7 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFFormulaEvaluator.cs @@ -0,0 +1,130 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using NPOI.SS.Formula; +using NPOI.SS.Formula.Udf; +using NPOI.SS.UserModel; +using NPOI.Util; +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFFormulaEvaluator : XSSFFormulaEvaluator + { + private static POILogger logger = POILogFactory.GetLogger(typeof(SXSSFFormulaEvaluator)); + + private IWorkbook wb; + + public SXSSFFormulaEvaluator(SXSSFWorkbook workbook) : this(workbook, null, null) + { + } + + private SXSSFFormulaEvaluator(SXSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) : this(workbook, new WorkbookEvaluator(SXSSFEvaluationWorkbook.Create(workbook), stabilityClassifier, udfFinder)) + { + + } + + private SXSSFFormulaEvaluator(SXSSFWorkbook workbook, WorkbookEvaluator bookEvaluator) : base(bookEvaluator) + { + this.wb = workbook; + } + + public static SXSSFFormulaEvaluator create(SXSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) + { + return new SXSSFFormulaEvaluator(workbook, stabilityClassifier, udfFinder); + } + + protected IEvaluationCell toEvaluationCell(ICell cell) + { + if (!(cell is SXSSFCell)) + { + throw new ArgumentException("Unexpected type of cell: " + cell.GetType() + "." + + " Only SXSSFCells can be evaluated."); + } + + return new SXSSFEvaluationCell((SXSSFCell)cell); + } + + public SXSSFCell EvaluateInCell(ICell cell) + { + return (SXSSFCell)base.EvaluateInCell(cell); + } + + public static void EvaluateAllFormulaCells(SXSSFWorkbook wb, bool skipOutOfWindow) + { + SXSSFFormulaEvaluator eval = new SXSSFFormulaEvaluator(wb); + + // Check they're all available + foreach (ISheet sheet in wb) + { + if (((SXSSFSheet)sheet).allFlushed) + { + throw new SheetsFlushedException(); + } + } + + // Process the sheets as best we can + foreach (ISheet sheet in wb) + { + + // Check if any rows have already been flushed out + int lastFlushedRowNum = ((SXSSFSheet)sheet).lastFlushedRowNumber; + if (lastFlushedRowNum > -1) + { + if (!skipOutOfWindow) throw new RowFlushedException(0); + logger.Log(POILogger.INFO, "Rows up to " + lastFlushedRowNum + " have already been flushed, skipping"); + } + + // Evaluate what we have + foreach (IRow r in sheet) + { + foreach (ICell c in r) + { + if (c.CellType == CellType.Formula) + { + eval.EvaluateFormulaCell(c); + } + } + } + } + } + + public void EvaluateAll() + { + // Have the evaluation done, with exceptions + EvaluateAllFormulaCells((SXSSFWorkbook)wb, false); + } + + } + + + public class SheetsFlushedException : Exception + { + public SheetsFlushedException() : base("One or more sheets have been flushed, cannot evaluate all cells") + { + + } + } + + public class RowFlushedException : Exception + { + public RowFlushedException(int rowNum) : base("Row " + rowNum + " has been flushed, cannot evaluate all cells") + { + + } + } +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFRow.cs b/src/NPOI.OOXML/Streaming/SXSSFRow.cs new file mode 100644 index 0000000..93b0bea --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFRow.cs @@ -0,0 +1,410 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using NPOI.SS; +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFRow : IRow, IComparable + { + private SXSSFSheet _sheet; // parent sheet + private SortedDictionary _cells = new SortedDictionary(); + private short _style = -1; // index of cell style in style table + private bool _zHeight; // row zero-height (this is somehow different than being hidden) + private float _height = -1; + + + // use Boolean to have a tri-state for on/off/undefined + public bool? Hidden { get; set; } + public bool? Collapsed { get; set; } + + public SXSSFRow(SXSSFSheet sheet) + { + _sheet = sheet; + } + + public IEnumerator allCellsIterator() + { + return new CellIterator(LastCellNum, null); + } + public bool HasCustomHeight() + { + return Height != -1; + } + + public List Cells + { + get { return _cells.Values.Select(cell => (ICell) cell).ToList(); } + } + + public short FirstCellNum + { + get + { + try + { + return (short) _cells.Keys.First(); + } + catch + { + return -1; + + } + } + } + + public short Height + { + get + { + return (short)(_height == -1 ? Sheet.DefaultRowHeightInPoints * 20 : _height); + } + set { _height = value; } + } + + public float HeightInPoints + { + get + { + return (float)(_height == -1 ? Sheet.DefaultRowHeightInPoints : _height / 20.0); + } + + set + { + _height = (value == -1) ? -1 : (value*20); + } + } + + public bool IsFormatted + { + get + { + return _style > -1; + } + } + + public short LastCellNum + { + get + { + return _cells.Count == 0 ? (short)-1 : Convert.ToInt16(_cells.Last().Key + 1); + + } + } + + public int OutlineLevel { get; set; } + + public int PhysicalNumberOfCells + { + get { return Cells.Count; } + } + + public int RowNum + { + get { throw new NotImplementedException();/*return Sheet.GetRow(this);*/ } + + set + { + throw new NotImplementedException(); + + } + } + + public ICellStyle RowStyle + { + get + { + if (!IsFormatted) return null; + + return Sheet.Workbook.GetCellStyleAt(_style); + } + + set + { + if (value == null) + { + _style = -1; + } + else + { + _style = value.Index; + } + } + } + + public ISheet Sheet + { + get { return _sheet; } + } + + public bool ZeroHeight + { + get { return _zHeight; } + + set { _zHeight = value; } + } + + public int CompareTo(SXSSFRow other) + { + if (this.Sheet != other.Sheet) + { + throw new InvalidOperationException("The compared rows must belong to the same sheet"); + } + + var thisRow = this.RowNum; + var otherRow = other.RowNum; + return thisRow.CompareTo(otherRow); + } + + public ICell CopyCell(int sourceIndex, int targetIndex) + { + throw new NotImplementedException(); + } + + public IRow CopyRowTo(int targetIndex) + { + throw new NotImplementedException(); + } + + public ICell CreateCell(int column) + { + return CreateCell(column, CellType.Blank); + } + + public ICell CreateCell(int column, CellType type) + { + CheckBounds(column); + SXSSFCell cell = new SXSSFCell(this, type); + _cells.Add(column, cell); + return cell; + } + + + /// + /// throws RuntimeException if the bounds are exceeded. + /// + /// + private static void CheckBounds(int cellIndex) + { + SpreadsheetVersion v = SpreadsheetVersion.EXCEL2007; + int maxcol = SpreadsheetVersion.EXCEL2007.LastColumnIndex; + if (cellIndex < 0 || cellIndex > maxcol) + { + throw new InvalidOperationException("Invalid column index (" + cellIndex + + "). Allowable column range for " + v.DefaultExtension + " is (0.." + + maxcol + ") or ('A'..'" + v.LastColumnName + "')"); + } + } + + public ICell GetCell(int cellnum) + { + var policy = _sheet.Workbook.MissingCellPolicy; + return GetCell(cellnum, policy); + } + + public ICell GetCell(int cellnum, MissingCellPolicy policy) + { + CheckBounds(cellnum); + + var cell = _cells[cellnum]; + + switch (policy._policy) + { + case MissingCellPolicy.Policy.RETURN_NULL_AND_BLANK: + return cell; + case MissingCellPolicy.Policy.RETURN_BLANK_AS_NULL: + bool isBlank = (cell != null && cell.CellType == CellType.Blank); + return (isBlank) ? null : cell; + case MissingCellPolicy.Policy.CREATE_NULL_AS_BLANK: + return (cell == null) ? CreateCell(cellnum, CellType.Blank) : cell; + default: + throw new InvalidOperationException("Illegal policy " + policy + " (" + policy.id + ")"); + } + } + + public IEnumerator GetEnumerator() + { + return new FilledCellIterator(_cells); + } + + public void MoveCell(ICell cell, int newColumn) + { + throw new NotImplementedException(); + } + + public void RemoveCell(ICell cell) + { + int index = getCellIndex((SXSSFCell)cell); + _cells.Remove(index); + } + /** + * Return the column number of a cell if it is in this row + * Otherwise return -1 + * + * @param cell the cell to get the index of + * @return cell column index if it is in this row, -1 otherwise + */ + /*package*/ + public int getCellIndex(SXSSFCell cell) + { + foreach (var entry in _cells) + { + if (entry.Value == cell) + { + return entry.Key; + } + } + return -1; + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + /** +* Create an iterator over the cells from [0, getLastCellNum()). +* Includes blank cells, excludes empty cells +* +* Returns an iterator over all filled cells (created via Row.createCell()) +* Throws ConcurrentModificationException if cells are added, moved, or +* removed after the iterator is created. +*/ + public class FilledCellIterator : IEnumerator + { + private SortedDictionary _cells; + private int pos = -1; + public FilledCellIterator(SortedDictionary cells) + { + _cells = cells; + } + + public ICell Current + { + get { return _cells[pos]; } + } + + object IEnumerator.Current + { + get + { + throw new NotImplementedException(); + } + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + return _cells.Values.GetEnumerator(); + } + + public bool MoveNext() + { + pos += 1; + return _cells.ContainsKey(pos); + } + + public void Reset() + { + throw new NotImplementedException(); + } + } + + public class CellIterator : IEnumerator + { + private Dictionary _cells; + private int maxColumn; + private int pos; + public CellIterator(int lastCellNum, Dictionary cells) + { + maxColumn = lastCellNum; //last column PLUS ONE, SHOULD BE DERIVED from cells enum. + pos = 0; + _cells = cells; + } + + + public ICell Current + { + get + { + throw new NotImplementedException(); + } + } + + object IEnumerator.Current + { + get + { + throw new NotImplementedException(); + } + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + public bool hasNext() + { + return pos < maxColumn; + } + + public bool MoveNext() + { + throw new NotImplementedException(); + } + + public ICell next() + { + if (hasNext()) + return _cells[pos++]; + else + throw new NullReferenceException(); + } + + public void remove() + { + throw new InvalidOperationException(); + } + + public void Reset() + { + throw new NotImplementedException(); + } + + + } + } + + + +} + + diff --git a/src/NPOI.OOXML/Streaming/SXSSFSheet.cs b/src/NPOI.OOXML/Streaming/SXSSFSheet.cs new file mode 100644 index 0000000..ac578e6 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFSheet.cs @@ -0,0 +1,989 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NPOI.SS; +using NPOI.SS.UserModel; +using NPOI.SS.Util; +using NPOI.Util; +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SXSSFSheet : ISheet + { + /*package*/ + public XSSFSheet _sh; + public SXSSFWorkbook _workbook; + //private TreeMap _rows = new TreeMap(); + public SortedDictionary _rows = new SortedDictionary(); + public SheetDataWriter _writer; + public int _randomAccessWindowSize = SXSSFWorkbook.DEFAULT_WINDOW_SIZE; + public AutoSizeColumnTracker _autoSizeColumnTracker; + public int outlineLevelRow = 0; + public int lastFlushedRowNumber = -1; + public bool allFlushed = false; + + + public SXSSFSheet(SXSSFWorkbook workbook, XSSFSheet xSheet) + { + _workbook = workbook; + _sh = xSheet; + _writer = workbook.CreateSheetDataWriter(); + SetRandomAccessWindowSize(_workbook.RandomAccessWindowSize); + _autoSizeColumnTracker = new AutoSizeColumnTracker(this); + } + public void SetRandomAccessWindowSize(int value) + { + if (value == 0 || value < -1) + { + throw new ArgumentException("RandomAccessWindowSize must be either -1 or a positive integer"); + } + _randomAccessWindowSize = value; + } + + + public bool Autobreaks + { + get + { + return _sh.Autobreaks; + } + + set { _sh.Autobreaks = value; } + } + + public int[] ColumnBreaks + { + get + { + return _sh.ColumnBreaks; + } + //set { _sh.ColumnBreaks = value; } + } + + public int DefaultColumnWidth + { + get + { + return _sh.DefaultColumnWidth; + } + + set + { + _sh.DefaultColumnWidth = value; + } + } + + public short DefaultRowHeight + { + get { return _sh.DefaultRowHeight; } + + set + { + _sh.DefaultRowHeight = value; + } + } + + public float DefaultRowHeightInPoints + { + get + { + return _sh.DefaultRowHeightInPoints; + } + + set + { + _sh.DefaultRowHeightInPoints = value; + } + } + + public bool DisplayFormulas + { + get + { + return _sh.DisplayFormulas; + } + + set { _sh.DisplayFormulas = value; } + } + + public bool DisplayGridlines + { + get + { + return _sh.DisplayGridlines; + } + + set + { + _sh.DisplayGridlines = value; + } + } + + public bool DisplayGuts + { + get { return _sh.DisplayGuts; } + + set + { + _sh.DisplayGuts = value; + } + } + + public bool DisplayRowColHeadings + { + get + { + return _sh.DisplayRowColHeadings; + } + + set + { + _sh.DisplayRowColHeadings = value; + } + } + + public bool DisplayZeros + { + get + { + return _sh.DisplayZeros; + } + + set + { + _sh.DisplayZeros = value; + } + } + + public IDrawing DrawingPatriarch + { + get + { + return _sh.DrawingPatriarch; + } + } + + public int FirstRowNum + { + get + { + if (_writer.NumberOfFlushedRows > 0) + return _writer.LowestIndexOfFlushedRows; + return _rows.Count == 0 ? 0 : _rows.Keys.First(); + } + } + + public bool FitToPage + { + get + { + return _sh.FitToPage; + } + + set { _sh.FitToPage = value; } + } + + public IFooter Footer + { + get + { + return _sh.Footer; + } + } + + public bool ForceFormulaRecalculation + { + get + { + return _sh.ForceFormulaRecalculation; + } + + set { _sh.ForceFormulaRecalculation = value; } + } + + public IHeader Header + { + get { return _sh.Header; } + } + + public bool HorizontallyCenter + { + get + { + return _sh.HorizontallyCenter; + } + + set { _sh.HorizontallyCenter = value; } + } + + public bool IsActive + { + get + { + throw new NotImplementedException(); + } + + set + { + throw new NotImplementedException(); + } + } + + public bool IsPrintGridlines + { + get { return _sh.IsPrintGridlines; } + + set + { + _sh.IsPrintGridlines = value; + } + } + + public bool IsRightToLeft + { + get + { + return _sh.IsRightToLeft; + } + + set + { + _sh.IsRightToLeft = value; + } + } + + public bool IsSelected + { + get + { + return _sh.IsSelected; + } + + set + { + _sh.IsSelected = value; + } + } + + public int LastRowNum + { + get + { + return _rows.Count == 0 ? 0 : _rows.Keys.Last(); + } + } + + public short LeftCol + { + get { return _sh.LeftCol; } + + set + { + throw new NotImplementedException(); + } + } + + public int NumMergedRegions + { + get { return _sh.NumMergedRegions; } + } + + public PaneInformation PaneInformation + { + get { return _sh.PaneInformation; } + } + + public int PhysicalNumberOfRows + { + get + { + return _rows.Count + _writer.NumberOfFlushedRows; + } + } + + public IPrintSetup PrintSetup + { + get { return _sh.PrintSetup; } + } + + public bool Protect + { + get { return _sh.Protect; } + } + + public CellRangeAddress RepeatingColumns + { + get { return _sh.RepeatingColumns; } + + set + { + _sh.RepeatingColumns = value; + } + } + + public CellRangeAddress RepeatingRows + { + get { return _sh.RepeatingRows; } + + set + { + _sh.RepeatingRows = value; + } + } + + public int[] RowBreaks + { + + get { return _sh.RowBreaks; } + + } + + public bool RowSumsBelow + { + get { return _sh.RowSumsBelow; } + + set + { + _sh.RowSumsBelow = value; + } + } + + public bool RowSumsRight + { + get { return _sh.RowSumsRight; } + + set + { + _sh.RowSumsRight = value; + } + } + + public bool ScenarioProtect + { + get { return _sh.ScenarioProtect; } + } + + public ISheetConditionalFormatting SheetConditionalFormatting + { + + get { return _sh.SheetConditionalFormatting; } + } + + public string SheetName + { + get { return _sh.SheetName; } + } + + public short TabColorIndex + { + get + { + throw new NotImplementedException(); + } + + set + { + throw new NotImplementedException(); + } + } + + public short TopRow + { + get { return _sh.TopRow; } + + set + { + _sh.TopRow = value; + } + } + + public bool VerticallyCenter + { + get { return _sh.VerticallyCenter; } + + set + { + _sh.VerticallyCenter = value; + } + } + + public IWorkbook Workbook + { + get { return _workbook; } + } + + public int AddMergedRegion(CellRangeAddress region) + { + return _sh.AddMergedRegion(region); + } + + public void AddValidationData(IDataValidation dataValidation) + { + _sh.AddValidationData(dataValidation); + } + + public void AutoSizeColumn(int column) + { + AutoSizeColumn(column, false); + } + + public void AutoSizeColumn(int column, bool useMergedCells) + { + // Multiple calls to autoSizeColumn need to look up the best-fit width + // of rows already flushed to disk plus re-calculate the best-fit width + // of rows in the current window. It isn't safe to update the column + // widths before flushing to disk because columns in the random access + // window rows may change in best-fit width. The best-fit width of a cell + // is only fixed when it becomes inaccessible for modification. + // Changes to the shared strings table, styles table, or formulas might + // be able to invalidate the auto-size width without the opportunity + // to recalculate the best-fit width for the flushed rows. This is an + // inherent limitation of SXSSF. If having correct auto-sizing is + // critical, the flushed rows would need to be re-read by the read-only + // XSSF eventmodel (SAX) or the memory-heavy XSSF usermodel (DOM). + int flushedWidth; + try + { + // get the best fit width of rows already flushed to disk + flushedWidth = _autoSizeColumnTracker.getBestFitColumnWidth(column, useMergedCells); + } + catch (Exception e) + { + throw new InvalidOperationException("Could not auto-size column. Make sure the column was tracked prior to auto-sizing the column.", e); + } + + // get the best-fit width of rows currently in the random access window + int activeWidth = (int)(256 * SheetUtil.GetColumnWidth(this, column, useMergedCells)); + + // the best-fit width for both flushed rows and random access window rows + // flushedWidth or activeWidth may be negative if column contains only blank cells + int bestFitWidth = Math.Max(flushedWidth, activeWidth); + + if (bestFitWidth > 0) + { + int maxColumnWidth = 255 * 256; // The maximum column width for an individual cell is 255 characters + int width = Math.Max(bestFitWidth, maxColumnWidth); + SetColumnWidth(column, width); + } + } + + public IRow CopyRow(int sourceIndex, int targetIndex) + { + throw new NotImplementedException(); + } + + public ISheet CopySheet(string Name) + { + throw new NotImplementedException(); + } + + public ISheet CopySheet(string Name, bool copyStyle) + { + throw new NotImplementedException(); + } + + public IDrawing CreateDrawingPatriarch() + { + throw new NotImplementedException(); + } + + public void CreateFreezePane(int colSplit, int rowSplit) + { + _sh.CreateFreezePane(colSplit, rowSplit); + } + + public void CreateFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) + { + _sh.CreateFreezePane(colSplit, rowSplit, leftmostColumn, topRow); + } + + public IRow CreateRow(int rownum) + { + int maxrow = SpreadsheetVersion.EXCEL2007.LastRowIndex; + if (rownum < 0 || rownum > maxrow) + { + throw new InvalidOperationException("Invalid row number (" + rownum + + ") outside allowable range (0.." + maxrow + ")"); + } + + // attempt to overwrite a row that is already flushed to disk + if (rownum <= _writer.NumberLastFlushedRow) + { + throw new InvalidOperationException( + "Attempting to write a row[" + rownum + "] " + + "in the range [0," + _writer.NumberLastFlushedRow + "] that is already written to disk."); + } + + // attempt to overwrite a existing row in the input template + if (_sh.PhysicalNumberOfRows > 0 && rownum <= _sh.LastRowNum) + { + throw new InvalidOperationException( + "Attempting to write a row[" + rownum + "] " + + "in the range [0," + _sh.LastRowNum + "] that is already written to disk."); + } + + SXSSFRow newRow = new SXSSFRow(this); + _rows.Add(rownum, newRow); + allFlushed = false; + if (_randomAccessWindowSize >= 0 && _rows.Count > _randomAccessWindowSize) + { + try + { + flushRows(_randomAccessWindowSize); + } + catch (IOException ioe) + { + throw new RuntimeException(ioe); + } + } + return newRow; + } + + public void CreateSplitPane(int xSplitPos, int ySplitPos, int leftmostColumn, int topRow, PanePosition activePane) + { + _sh.CreateSplitPane(xSplitPos, ySplitPos, leftmostColumn, topRow, activePane); + } + + public IComment GetCellComment(int row, int column) + { + return _sh.GetCellComment(row, column); + } + + public int GetColumnOutlineLevel(int columnIndex) + { + return _sh.GetColumnOutlineLevel(columnIndex); + } + + public ICellStyle GetColumnStyle(int column) + { + return _sh.GetColumnStyle(column); + } + + public int GetColumnWidth(int columnIndex) + { + return _sh.GetColumnWidth(columnIndex); + } + + public float GetColumnWidthInPixels(int columnIndex) + { + return _sh.GetColumnWidthInPixels(columnIndex); + } + + + public IDataValidationHelper GetDataValidationHelper() + { + return _sh.GetDataValidationHelper(); + } + + public List GetDataValidations() + { + return _sh.GetDataValidations(); + } + + public IEnumerator GetEnumerator() + { + return _sh.GetEnumerator(); + } + + public double GetMargin(MarginType margin) + { + return _sh.GetMargin(margin); + } + + public CellRangeAddress GetMergedRegion(int index) + { + return _sh.GetMergedRegion(index); + } + + public IRow GetRow(int rownum) + { + return _rows[rownum]; + } + + public IEnumerator GetRowEnumerator() + { + return _sh.GetRowEnumerator(); + } + + public void GroupColumn(int fromColumn, int toColumn) + { + _sh.GroupColumn(fromColumn, toColumn); + } + + + //TODO: test + public void GroupRow(int fromRow, int toRow) + { + var groupRows = _rows.Where(kvp => kvp.Key >= fromRow && kvp.Key <= toRow + 1).Select(r => r.Value); + foreach (SXSSFRow row in groupRows) + { + int level = row.OutlineLevel + 1; + row.OutlineLevel = level; + + if (level > outlineLevelRow) outlineLevelRow = level; + } + + SetWorksheetOutlineLevelRow(); + } + + /** + * Set row groupings (like groupRow) in a stream-friendly manner + * + *

+ * groupRows requires all rows in the group to be in the current window. + * This is not always practical. Instead use setRowOutlineLevel to + * explicitly set the group level. Level 1 is the top level group, + * followed by 2, etc. It is up to the user to ensure that level 2 + * groups are correctly nested under level 1, etc. + *

+ * + * @param rownum index of row to update (0-based) + * @param level outline level (greater than 0) + */ + public void SetRowOutlineLevel(int rownum, int level) + { + SXSSFRow row = _rows[rownum]; + + row.OutlineLevel = level; + if (level > 0 && level > outlineLevelRow) + { + outlineLevelRow = level; + SetWorksheetOutlineLevelRow(); + } + } + + private void SetWorksheetOutlineLevelRow() + { + var ct = _sh.GetCTWorksheet(); + var pr = ct.IsSetSheetFormatPr() ? + ct.sheetFormatPr : + ct.AddNewSheetFormatPr(); + if (outlineLevelRow > 0) pr.outlineLevelRow = (byte)outlineLevelRow; + } + + public bool IsColumnBroken(int column) + { + return _sh.IsColumnBroken(column); + } + + public bool IsColumnHidden(int columnIndex) + { + return _sh.IsColumnHidden(columnIndex); + } + + public bool IsMergedRegion(CellRangeAddress mergedRegion) + { + throw new NotImplementedException(); + } + + public bool IsRowBroken(int row) + { + return _sh.IsRowBroken(row); + } + + public void ProtectSheet(string password) + { + _sh.ProtectSheet(password); + } + + public ICellRange RemoveArrayFormula(ICell cell) + { + return _sh.RemoveArrayFormula(cell); + } + + public void RemoveColumnBreak(int column) + { + _sh.RemoveColumnBreak(column); + } + + public void RemoveMergedRegion(int index) + { + _sh.RemoveMergedRegion(index); + } + + public void RemoveRow(IRow row) + { + throw new NotImplementedException(); + //if (row.Sheet != this) + //{ + // throw new InvalidOperationException("Specified row does not belong to this sheet"); + //} + + + //for (Iterator> iter = _rows.entrySet().iterator(); iter.hasNext();) + //{ + // Map.Entry entry = iter.next(); + // if (entry.getValue() == row) + // { + // iter.remove(); + // return; + // } + //} + } + + public void RemoveRowBreak(int row) + { + _sh.RemoveRowBreak(row); + } + + public void SetActive(bool value) + { + throw new NotImplementedException(); + } + + public void SetActiveCell(int row, int column) + { + throw new NotImplementedException(); + } + + public void SetActiveCellRange(List cellranges, int activeRange, int activeRow, int activeColumn) + { + throw new NotImplementedException(); + } + + public void SetActiveCellRange(int firstRow, int lastRow, int firstColumn, int lastColumn) + { + throw new NotImplementedException(); + } + + public ICellRange SetArrayFormula(string formula, CellRangeAddress range) + { + return _sh.SetArrayFormula(formula, range); + } + + public IAutoFilter SetAutoFilter(CellRangeAddress range) + { + return _sh.SetAutoFilter(range); + } + + public void SetColumnBreak(int column) + { + _sh.SetColumnBreak(column); + } + + public void SetColumnGroupCollapsed(int columnNumber, bool collapsed) + { + _sh.SetColumnGroupCollapsed(columnNumber, collapsed); + } + + public void SetColumnHidden(int columnIndex, bool hidden) + { + _sh.SetColumnHidden(columnIndex, hidden); + } + + public void SetColumnWidth(int columnIndex, int width) + { + _sh.SetColumnWidth(columnIndex, width); + } + + public void SetDefaultColumnStyle(int column, ICellStyle style) + { + _sh.SetDefaultColumnStyle(column, style); + } + + public void SetMargin(MarginType margin, double size) + { + _sh.SetMargin(margin, size); + } + + public void SetRowBreak(int row) + { + _sh.SetRowBreak(row); + } + + public void SetRowGroupCollapsed(int row, bool collapse) + { + if (collapse) + { + collapseRow(row); + } + else + { + //expandRow(rowIndex); + throw new RuntimeException("Unable to expand row: Not Implemented"); + } + } + + private void collapseRow(int rowIndex) + { + SXSSFRow row = (SXSSFRow)GetRow(rowIndex); + if (row == null) + { + throw new InvalidOperationException("Invalid row number(" + rowIndex + "). Row does not exist."); + } + else + { + int startRow = FindStartOfRowOutlineGroup(rowIndex); + + // Hide all the columns until the end of the group + int lastRow = WriteHidden(row, startRow, true); + SXSSFRow lastRowObj = (SXSSFRow)GetRow(lastRow); + if (lastRowObj != null) + { + lastRowObj.Collapsed = true; + } + else + { + SXSSFRow newRow = (SXSSFRow)CreateRow(lastRow); + newRow.Collapsed = true; + } + } + } + + /** + * @param rowIndex the zero based row index to find from + */ + private int FindStartOfRowOutlineGroup(int rowIndex) + { + // Find the start of the group. + IRow row = GetRow(rowIndex); + int level = ((SXSSFRow)row).OutlineLevel; + if (level == 0) + { + throw new InvalidOperationException("Outline level is zero for the row (" + rowIndex + ")."); + } + int currentRow = rowIndex; + while (GetRow(currentRow) != null) + { + if (GetRow(currentRow).OutlineLevel < level) + return currentRow + 1; + currentRow--; + } + return currentRow + 1; + } + + private int WriteHidden(SXSSFRow xRow, int rowIndex, bool hidden) + { + int level = xRow.OutlineLevel; + var currRow = (SXSSFRow)GetRow(rowIndex); + + while (currRow != null && currRow.OutlineLevel >= level) + { + currRow.Hidden = hidden; + rowIndex++; + currRow = (SXSSFRow)GetRow(rowIndex); + } + return rowIndex; + } + + [Obsolete("in poi 3.16")] + public void SetZoom(int numerator, int denominator) + { + _sh.SetZoom(numerator, denominator); + } + + public void ShiftRows(int startRow, int endRow, int n) + { + throw new NotImplementedException(); + } + + public void ShiftRows(int startRow, int endRow, int n, bool copyRowHeight, bool resetOriginalRowHeight) + { + throw new NotImplementedException(); + } + + public void ShowInPane(short toprow, short leftcol) + { + _sh.ShowInPane(toprow, leftcol); + } + + public void ShowInPane(int toprow, int leftcol) + { + _sh.ShowInPane(toprow, leftcol); + } + + public void UngroupColumn(int fromColumn, int toColumn) + { + _sh.UngroupColumn(fromColumn, toColumn); + + } + + public void UngroupRow(int fromRow, int toRow) + { + _sh.UngroupRow(fromRow, toRow); + } + + public bool IsDate1904() + { + throw new NotImplementedException(); + } + + public void changeRowNum(SXSSFRow row, int newRowNum) + { + + RemoveRow(row); + _rows.Add(newRowNum, row); + } + + public bool dispose() + { + if (!allFlushed) flushRows(); + return _writer.Dispose(); + } + + /** + * Specifies how many rows can be accessed at most via getRow(). + * The exeeding rows (if any) are flushed to the disk while rows + * with lower index values are flushed first. + */ + private void flushRows(int remaining) + { + while (_rows.Count > remaining) flushOneRow(); + if (remaining == 0) allFlushed = true; + } + + public void flushRows() + { + flushRows(0); + } + + private void flushOneRow() + { + + int firstRowNum = _rows.FirstOrDefault().Key; + if (firstRowNum != null) + { + int rowIndex = firstRowNum; + SXSSFRow row = _rows[firstRowNum]; + // Update the best fit column widths for auto-sizing just before the rows are flushed + // _autoSizeColumnTracker.UpdateColumnWidths(row); + _writer.WriteRow(rowIndex, row); + _rows.Remove(firstRowNum); + lastFlushedRowNumber = rowIndex; + } + } + + /* Gets "" document fragment*/ + public Stream getWorksheetXMLInputStream() + { + // flush all remaining data and close the temp file writer + flushRows(0); + _writer.Close(); + return _writer.GetWorksheetXmlInputStream(); + } + + public SheetDataWriter getSheetDataWriter() + { + return _writer; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/SXSSFWorkbook.cs b/src/NPOI.OOXML/Streaming/SXSSFWorkbook.cs new file mode 100644 index 0000000..4dc883f --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SXSSFWorkbook.cs @@ -0,0 +1,736 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Text; +using ICSharpCode.SharpZipLib.Zip; +using NPOI.OpenXml4Net.Util; +using NPOI.SS.Formula.Udf; +using NPOI.SS.UserModel; +using NPOI.Util; +using NPOI.XSSF.Model; +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + /// + /// Streaming version of the XSSFWorkbook, originally implemented in the "BigGridDemo". + /// + public class SXSSFWorkbook : IWorkbook + { + private static readonly POILogger logger = POILogFactory.GetLogger(typeof(SXSSFWorkbook)); + + public const int DEFAULT_WINDOW_SIZE = 100; + + public XSSFWorkbook XssfWorkbook; + + private Dictionary _sxFromXHash = new Dictionary(); + private Dictionary _xFromSxHash = new Dictionary(); + + private int _randomAccessWindowSize = DEFAULT_WINDOW_SIZE; + + public int RandomAccessWindowSize + { + get { return _randomAccessWindowSize; } + set + { + if (value <= 0) + { + throw new ArgumentException("rowAccessWindowSize must be greater than 0 or -1"); + } + _randomAccessWindowSize = value; + } + + } + + /// + /// whether temp file should be compresss. + /// + private bool _compressTmpFiles = false; + + /// + /// shared string table - a cache of strings in this workbook. + /// + private SharedStringsTable _sharedStringSource; + + public int ActiveSheetIndex + { + get { return XssfWorkbook.ActiveSheetIndex; } + } + + public int FirstVisibleTab + { + get { return XssfWorkbook.FirstVisibleTab; } + + set { XssfWorkbook.FirstVisibleTab = value; } + } + + public int NumberOfSheets + { + get { return XssfWorkbook.NumberOfSheets; } + } + + public short NumberOfFonts + { + get { return XssfWorkbook.NumberOfFonts; } + } + + public short NumCellStyles + { + get { return XssfWorkbook.NumCellStyles; } + } + + public int NumberOfNames + { + get { return XssfWorkbook.NumberOfNames; } + } + + public MissingCellPolicy MissingCellPolicy + { + get { return XssfWorkbook.MissingCellPolicy; } + + set { XssfWorkbook.MissingCellPolicy = value; } + } + + public bool IsHidden + { + get { return XssfWorkbook.IsHidden; } + + set { XssfWorkbook.IsHidden = value; } + } + + + #region Constructors + + public SXSSFWorkbook() : this(null) + { + + } + + public SXSSFWorkbook(XSSFWorkbook workbook) : this(workbook, DEFAULT_WINDOW_SIZE) + { + + } + + public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize) + : this(workbook, rowAccessWindowSize, false) + { + + } + + public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, bool compressTmpFiles) + : this(workbook, rowAccessWindowSize, compressTmpFiles, false) + { + + } + + /// + /// Currently only supports writing not reading. E.g. the number of rows returned from a worksheet will be wrong etc. + /// + /// + /// + /// + /// + public SXSSFWorkbook(XSSFWorkbook workbook, int rowAccessWindowSize, bool compressTmpFiles, bool useSharedStringsTable) + { + RandomAccessWindowSize = rowAccessWindowSize; + + _compressTmpFiles = compressTmpFiles; + + if (workbook == null) + { + XssfWorkbook = new XSSFWorkbook(); + _sharedStringSource = useSharedStringsTable ? XssfWorkbook.GetSharedStringSource() : null; + } + else + { + XssfWorkbook = workbook; + _sharedStringSource = useSharedStringsTable ? XssfWorkbook.GetSharedStringSource() : null; + var numberOfSheets = XssfWorkbook.NumberOfSheets; + for (int i = 0; i < numberOfSheets; i++) + { + XSSFSheet sheet = (XSSFSheet)XssfWorkbook.GetSheetAt(i); + CreateAndRegisterSXSSFSheet(sheet); + } + } + } + + #endregion + + private SXSSFSheet CreateAndRegisterSXSSFSheet(ISheet xSheet) + { + SXSSFSheet sxSheet; + try + { + sxSheet = new SXSSFSheet(this, (XSSFSheet)xSheet); + } + catch (IOException ioe) + { + throw new RuntimeException(ioe); + } + RegisterSheetMapping(sxSheet, (XSSFSheet)xSheet); + return sxSheet; + } + + private void RegisterSheetMapping(SXSSFSheet sxSheet, XSSFSheet xSheet) + { + _sxFromXHash.Add(sxSheet, xSheet); + _xFromSxHash.Add(xSheet, sxSheet); + } + + private void DeregisterSheetMapping(XSSFSheet xSheet) + { + SXSSFSheet sxSheet = GetSXSSFSheet(xSheet); + + try + { + sxSheet._writer.Close(); + } + catch (IOException e) + { + // ignore exception here + } + + _sxFromXHash.Remove(sxSheet); + + _xFromSxHash.Remove(xSheet); + } + + + private XSSFSheet GetXSSFSheet(SXSSFSheet sheet) + { + return _sxFromXHash[sheet]; + } + + private SXSSFSheet GetSXSSFSheet(XSSFSheet sheet) + { + return _xFromSxHash[sheet]; + } + + public SheetDataWriter CreateSheetDataWriter() + { + if (_compressTmpFiles) + { + return new GZIPSheetDataWriter(_sharedStringSource); + } + + return new SheetDataWriter(_sharedStringSource); + } + + private XSSFSheet GetSheetFromZipEntryName(string sheetRef) + { + foreach (XSSFSheet sheet in _sxFromXHash.Values) + { + if (sheetRef.Equals(sheet.GetPackagePart().PartName.Name.Substring(1))) return sheet; + } + return null; + } + + private void InjectData(ZipEntrySource zipEntrySource, Stream outStream) + { + try + { + ZipOutputStream zos = new ZipOutputStream(outStream); + try + { + var en = zipEntrySource.Entries; + while (en.MoveNext()) + { + var ze = (ZipEntry)en.Current; + zos.PutNextEntry(new ZipEntry(ze.Name)); + var inputStream = zipEntrySource.GetInputStream(ze); + XSSFSheet xSheet = GetSheetFromZipEntryName(ze.Name); + if (xSheet != null) + { + SXSSFSheet sxSheet = GetSXSSFSheet(xSheet); + var xis = sxSheet.getWorksheetXMLInputStream(); + try + { + CopyStreamAndInjectWorksheet(inputStream, zos, xis); + } + finally + { + xis.Close(); + } + } + else + { + CopyStream(inputStream, zos); + } + inputStream.Close(); + } + } + finally + { + zos.Close(); + } + } + finally + { + zipEntrySource.Close(); + } + } + + private static void CopyStream(Stream inputStream, Stream outputStream) + { + var chunk = new byte[1024]; + int count; + + while ((count = inputStream.Read(chunk, 0, chunk.Length)) > 0) + { + outputStream.Write(chunk, 0, count); + } + } + + private static void CopyStreamAndInjectWorksheet(Stream inputStream, Stream outputStream, Stream worksheetData) + { + StreamReader inReader = new StreamReader(inputStream, Encoding.UTF8); + StreamWriter outWriter = new StreamWriter(outputStream, Encoding.UTF8); + bool needsStartTag = true; + int c; + int pos = 0; + String s = "" or "" (excluding). + while (((c = inReader.Read()) != -1)) + { + if ((char)c == (char)s[pos]) + { + pos++; + if (pos == n) + { + if ("') + { + // Found + outWriter.Write(s); + sb.Append(s); + outWriter.Write((char)c); + sb.Append((char) c); + s = ""; + n = s.Length; + pos = 0; + needsStartTag = false; + continue; + } + if ((char)c == '/') + { + // Found ') + { + // Found + break; + } + + outWriter.Write(s); + sb.Append(s); + outWriter.Write('/'); + sb.Append('/'); + outWriter.Write((char)c); + sb.Append((char) c); + pos = 0; + continue; + } + + outWriter.Write(s); + sb.Append(s); + outWriter.Write('/'); + sb.Append('/'); + outWriter.Write((char)c); + sb.Append((char)c); + pos = 0; + continue; + } + else + { + // Found + break; + } + } + } + else + { + if (pos > 0) + { + outWriter.Write(s.Substring(0,pos)); + sb.Append(s, 0, pos); + } + if (c == s[0]) + { + pos = 1; + } + else + { + outWriter.Write((char)c); + sb.Append((char) c); + pos = 0; + } + } + } + outWriter.Flush(); + if (needsStartTag) + { + outWriter.Write("\n"); + sb.Append("\n"); + outWriter.Flush(); + } + //Copy the worksheet data to "out". + CopyStream(worksheetData, outputStream); + outWriter.Write(""); + outWriter.Flush(); + //Copy the rest of "in" to "out". + while (((c = inReader.Read()) != -1)) + { + outWriter.Write((char) c); + sb.Append((char)c); + } + outWriter.Flush(); + + } + + public void SetSheetOrder(string sheetname, int pos) + { + XssfWorkbook.SetSheetOrder(sheetname, pos); + } + + public void SetSelectedTab(int index) + { + XssfWorkbook.SetSelectedTab(index); + } + + public void SetActiveSheet(int sheetIndex) + { + XssfWorkbook.SetActiveSheet(sheetIndex); + } + + public string GetSheetName(int sheet) + { + return XssfWorkbook.GetSheetName(sheet); + } + + public void SetSheetName(int sheet, string name) + { + XssfWorkbook.SetSheetName(sheet, name); + } + + public int GetSheetIndex(string name) + { + return XssfWorkbook.GetSheetIndex(name); + } + + public int GetSheetIndex(ISheet sheet) + { + return XssfWorkbook.GetSheetIndex(GetXSSFSheet((SXSSFSheet)sheet)); + } + + public ISheet CreateSheet() + { + return CreateAndRegisterSXSSFSheet(XssfWorkbook.CreateSheet()); + } + + public ISheet CreateSheet(string sheetname) + { + return CreateAndRegisterSXSSFSheet(XssfWorkbook.CreateSheet(sheetname)); + } + + public ISheet CloneSheet(int sheetNum) + { + throw new NotImplementedException(); + } + + public ISheet GetSheetAt(int index) + { + return GetSXSSFSheet((XSSFSheet)XssfWorkbook.GetSheetAt(index)); + } + + public ISheet GetSheet(string name) + { + return GetSXSSFSheet((XSSFSheet)XssfWorkbook.GetSheet(name)); + } + + public void RemoveSheetAt(int index) + { + // Get the sheet to be removed + var xSheet = (XSSFSheet)XssfWorkbook.GetSheetAt(index); + var sxSheet = GetSXSSFSheet(xSheet); + + // De-register it + XssfWorkbook.RemoveSheetAt(index); + DeregisterSheetMapping(xSheet); + + // Clean up temporary resources + try + { + sxSheet.dispose(); + } + catch (IOException e) + { + logger.Log(POILogger.WARN, e); + } + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + public void SetRepeatingRowsAndColumns(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) + { + throw new NotImplementedException(); + } + + public IFont CreateFont() + { + return XssfWorkbook.CreateFont(); + } + + [Obsolete("deprecated in poi 3.16")] + public IFont FindFont(short boldWeight, short color, short fontHeight, string name, bool italic, bool strikeout, FontSuperScript typeOffset, FontUnderlineType underline) + { + return XssfWorkbook.FindFont(boldWeight, color, fontHeight, name, italic, strikeout, typeOffset, underline); + } + + public IFont GetFontAt(short idx) + { + return XssfWorkbook.GetFontAt(idx); + } + + public ICellStyle CreateCellStyle() + { + return XssfWorkbook.CreateCellStyle(); + } + + public ICellStyle GetCellStyleAt(short idx) + { + return XssfWorkbook.GetCellStyleAt(idx); + } + + public void Write(Stream stream) + { + FlushSheets(); + + //Save the template + var tmplFile = TempFile.CreateTempFile("poi-sxssf-template", ".xlsx"); + try + { + var os = new FileStream(tmplFile.FullName, FileMode.Open, FileAccess.ReadWrite); + try + { + XssfWorkbook.Write(os); + } + finally + { + os.Close(); + } + + //Substitute the template entries with the generated sheet data files + ZipEntrySource source = new ZipFileZipEntrySource(new ZipFile(tmplFile.FullName)); + InjectData(source, stream); + } + finally + { + tmplFile.Delete(); + if (File.Exists(tmplFile.FullName)) + { + throw new IOException("Could not delete temporary file after processing: " + tmplFile); + } + } + } + + private void FlushSheets() + { + foreach (SXSSFSheet sheet in _xFromSxHash.Values) + { + sheet.flushRows(); + } + } + + /** + * Dispose of temporary files backing this workbook on disk. + * Calling this method will render the workbook unusable. + * @return true if all temporary files were deleted successfully. + */ + public bool Dispose() + { + var success = true; + foreach (SXSSFSheet sheet in _sxFromXHash.Keys) + { + try + { + success = sheet.dispose() && success; + } + catch (IOException e) + { + logger.Log(POILogger.WARN, e); + success = false; + } + } + return success; + } + + public IName GetName(string name) + { + return XssfWorkbook.GetName(name); + } + [Obsolete("Deprecated in 3.16 throws an error.")] + public IName GetNameAt(int nameIndex) + { + return XssfWorkbook.GetNameAt(nameIndex); + } + + public IName CreateName() + { + return XssfWorkbook.CreateName(); + } + + [Obsolete("deprecated in 3.16 New projects should avoid accessing named ranges by index. GetName(String)} instead.")] + public int GetNameIndex(string name) + { + return XssfWorkbook.GetNameIndex(name); + } + + [Obsolete("deprecated in 3.16 New projects should use RemoveName(Name)")] + public void RemoveName(int index) + { + XssfWorkbook.RemoveName(index); + } + + [Obsolete("deprecated in 3.16 New projects should use RemoveName(IName Name)")] + public void RemoveName(string name) + { + XssfWorkbook.RemoveName(name); + } + + public int LinkExternalWorkbook(string name, IWorkbook workbook) + { + throw new NotImplementedException(); + } + + public void SetPrintArea(int sheetIndex, string reference) + { + XssfWorkbook.SetPrintArea(sheetIndex, reference); + } + + public void SetPrintArea(int sheetIndex, int startColumn, int endColumn, int startRow, int endRow) + { + XssfWorkbook.SetPrintArea(sheetIndex, startColumn, endColumn, startRow, endRow); + } + + public string GetPrintArea(int sheetIndex) + { + return XssfWorkbook.GetPrintArea(sheetIndex); + } + + public void RemovePrintArea(int sheetIndex) + { + XssfWorkbook.RemovePrintArea(sheetIndex); + } + + + public IDataFormat CreateDataFormat() + { + return XssfWorkbook.CreateDataFormat(); + } + + public int AddPicture(byte[] pictureData, PictureType format) + { + return XssfWorkbook.AddPicture(pictureData, format); + } + + public IList GetAllPictures() + { + return XssfWorkbook.GetAllPictures(); + } + + public ICreationHelper GetCreationHelper() + { + return new SXSSFCreationHelper(this); + } + + public bool IsSheetHidden(int sheetIx) + { + return XssfWorkbook.IsSheetHidden(sheetIx); + } + + public bool IsSheetVeryHidden(int sheetIx) + { + return XssfWorkbook.IsSheetVeryHidden(sheetIx); + } + + public void SetSheetHidden(int sheetIx, SheetState hidden) + { + XssfWorkbook.SetSheetHidden(sheetIx, hidden); + } + + public void SetSheetHidden(int sheetIx, int hidden) + { + XssfWorkbook.SetSheetHidden(sheetIx, hidden); + } + + public void AddToolPack(UDFFinder toopack) + { + XssfWorkbook.AddToolPack(toopack); + } + + public void Close() + { + // ensure that any lingering writer is closed + foreach (SXSSFSheet sheet in _xFromSxHash.Values) + { + try + { + sheet._writer.Close(); + } + catch (IOException e) + { + logger.Log(POILogger.WARN, + "An exception occurred while closing sheet data writer for sheet " + + sheet.SheetName + ".", e); + } + } + + + // Tell the base workbook to close, does nothing if + // it's a newly created one + XssfWorkbook.Close(); + } + + //TODO: missing methods from POI 3.16 setForceFormulaRecalculation, GetForceFormulaRecalulation, GetSpreadsheetVersion + //TODO: missing method isDate1904, isHidden, setHidden + } +} diff --git a/src/NPOI.OOXML/Streaming/SheetDataWriter.cs b/src/NPOI.OOXML/Streaming/SheetDataWriter.cs new file mode 100644 index 0000000..f95960f --- /dev/null +++ b/src/NPOI.OOXML/Streaming/SheetDataWriter.cs @@ -0,0 +1,532 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using System; +using System.IO; +using System.Linq; +using System.Text; +using NPOI.OpenXmlFormats.Spreadsheet; +using NPOI.SS.UserModel; +using NPOI.SS.Util; +using NPOI.Util; +using NPOI.XSSF.Model; +using NPOI.XSSF.UserModel; + +namespace NPOI.XSSF.Streaming +{ + public class SheetDataWriter + { + private static POILogger logger = POILogFactory.GetLogger(typeof(SheetDataWriter)); + + protected FileInfo TemporaryFileInfo { get; set; } + protected Stream OutputStream { get; set; } + private int RowNum { get; set; } + public int NumberOfFlushedRows { get; set; } + public int LowestIndexOfFlushedRows { get; set; } // meaningful only of _numberOfFlushedRows>0 + public int NumberOfCellsOfLastFlushedRow { get; set; } // meaningful only of _numberOfFlushedRows>0 + public int NumberLastFlushedRow = -1; // meaningful only of _numberOfFlushedRows>0 + + /** + * Table of strings shared across this workbook. + * If two cells contain the same string, then the cell value is the same index into SharedStringsTable + */ + private SharedStringsTable _sharedStringSource; + + public SheetDataWriter() + { + TemporaryFileInfo = CreateTempFile(); + OutputStream = CreateWriter(TemporaryFileInfo); + } + public SheetDataWriter(SharedStringsTable sharedStringsTable) : this() + { + _sharedStringSource = sharedStringsTable; + } + /** + * Create a temp file to write sheet data. + * By default, temp files are created in the default temporary-file directory + * with a prefix "poi-sxssf-sheet" and suffix ".xml". Subclasses can override + * it and specify a different temp directory or filename or suffix, e.g. .gz + * + * @return temp file to write sheet data + */ + + public virtual FileInfo CreateTempFile() + { + return TempFile.CreateTempFile("poi-sxssf-sheet", ".xml"); + } + + /** + * Create a writer for the sheet data. + * + * @param fd the file to write to + */ + public virtual Stream CreateWriter(FileInfo fd) + { + + FileStream fos = new FileStream(fd.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite); + Stream outputStream = null; + try + { + outputStream = DecorateOutputStream(fos); + } + catch (Exception e) + { + fos.Close(); + throw e; + } + + return outputStream; + } + + /** + * Override this to translate (such as encrypt or compress) the file output stream + * as it is being written to disk. + * The default behavior is to to pass the stream through unmodified. + * + * @param fos the stream to decorate + * @return a decorated stream + * @throws IOException + * @see #decorateInputStream(FileInputStream) + */ + protected virtual Stream DecorateOutputStream(Stream fos) + { + return fos; + } + + /** + * flush and close the temp data writer. + * This method must be invoked before calling {@link #getWorksheetXMLInputStream()} + */ + public void Close() + { + try + { + OutputStream.Flush(); + } + catch (Exception e) + { + + } + try + { + OutputStream.Close(); + } + catch (Exception e) + { + + } + + + } + + /** + * @return a stream to read temp file with the sheet data + */ + public Stream GetWorksheetXmlInputStream() + { + Stream fis = new FileStream(TemporaryFileInfo.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite); + try + { + return DecorateInputStream(fis); + } + catch (IOException e) + { + fis.Close(); + throw e; + } + } + + /** + * Override this to translate (such as decrypt or expand) the file input stream + * as it is being read from disk. + * The default behavior is to to pass the stream through unmodified. + * + * @param fis the stream to decorate + * @return a decorated stream + * @throws IOException + * @see #decorateOutputStream(FileOutputStream) + */ + protected virtual Stream DecorateInputStream(Stream fis) + { + return fis; + } + + + + protected void Finalize() + { + TemporaryFileInfo.Delete(); + if (File.Exists(TemporaryFileInfo.FullName)) + { + logger.Log(POILogger.ERROR, "Can't delete temporary encryption file: " + TemporaryFileInfo); + } + } + + /** + * Write a row to the file + * + * @param rownum 0-based row number + * @param row a row + */ + public void WriteRow(int rownum, IRow row) + { + if (NumberOfFlushedRows == 0) + { + LowestIndexOfFlushedRows = rownum; + } + + NumberLastFlushedRow = Math.Max(rownum, NumberLastFlushedRow); + NumberOfCellsOfLastFlushedRow = row.LastCellNum; + NumberOfFlushedRows++; + BeginRow(rownum, row); + var cells = row.GetEnumerator(); + int columnIndex = 0; + while (cells.MoveNext()) + { + WriteCell(columnIndex++, cells.Current); + } + EndRow(); + } + + private void BeginRow(int rownum, IRow row) + { + WriteAsBytes(OutputStream, "\n"); + + } + + public void WriteCell(int columnIndex, ICell cell) + { + if (cell == null) + { + return; + } + string cellRef = new CellReference(RowNum, columnIndex).FormatAsString(); + WriteAsBytes(OutputStream, ""); + break; + } + case CellType.Formula: + { + WriteAsBytes(OutputStream, ">"); + WriteAsBytes(OutputStream, ""); + + OutputQuotedString(cell.CellFormula); + + WriteAsBytes(OutputStream, ""); + + switch (cell.GetCachedFormulaResultTypeEnum()) + { + case CellType.Numeric: + double nval = cell.NumericCellValue; + if (!Double.IsNaN(nval)) + { + WriteAsBytes(OutputStream, "" + nval + ""); + } + break; + default: + break; + } + break; + } + case CellType.String: + { + if (_sharedStringSource != null) + { + XSSFRichTextString rt = new XSSFRichTextString(cell.StringCellValue); + int sRef = _sharedStringSource.AddEntry(rt.GetCTRst()); + + WriteAsBytes(OutputStream, " t=\"" + ST_CellType.s + "\">"); + WriteAsBytes(OutputStream, ""); + WriteAsBytes(OutputStream, sRef.ToString()); + WriteAsBytes(OutputStream, ""); + } + else + { + WriteAsBytes(OutputStream, " t=\"inlineStr\">"); + WriteAsBytes(OutputStream, ""); + + OutputQuotedString(cell.StringCellValue); + + WriteAsBytes(OutputStream, ""); + } + break; + } + case CellType.Numeric: + { + WriteAsBytes(OutputStream, " t=\"n\">"); + WriteAsBytes(OutputStream, "" + cell.NumericCellValue + ""); + break; + } + case CellType.Boolean: + { + WriteAsBytes(OutputStream, " t=\"b\">"); + WriteAsBytes(OutputStream, "" + (cell.BooleanCellValue ? "1" : "0") + ""); + break; + } + case CellType.Error: + { + FormulaError error = FormulaError.ForInt(cell.ErrorCellValue); + + WriteAsBytes(OutputStream, " t=\"e\">"); + WriteAsBytes(OutputStream, "" + error.String + ""); + break; + } + default: + { + throw new InvalidOperationException("Invalid cell type: " + cell.CellType); + } + } + WriteAsBytes(OutputStream, ""); + OutputStream.Flush(); + } + + private void WriteAsBytes(Stream outStream, string text) + { + var bytes = Encoding.UTF8.GetBytes(text); + outStream.Write(bytes, 0, bytes.Length); + } + + private void WriteAsBytes(Stream outStream, char[] chars) + { + var bytes = Encoding.UTF8.GetBytes(chars); + outStream.Write(bytes, 0, bytes.Length); + } + /** + * @return whether the string has leading / trailing spaces that + * need to be preserved with the xml:space=\"preserve\" attribute + */ + private bool HasLeadingTrailingSpaces(string str) + { + if (str != null && str.Length > 0) + { + char firstChar = str[0]; + char lastChar = str[str.Length - 1]; + return Character.isWhitespace(firstChar) || Character.isWhitespace(lastChar); + } + return false; + } + + //Taken from jdk1.3/src/javax/swing/text/html/HTMLWriter.java + protected void OutputQuotedString(String s) + { + if (s == null || s.Length == 0) + { + return; + } + + char[] chars = s.ToCharArray(); + int last = 0; + int length = s.Length; + for (int counter = 0; counter < length; counter++) + { + char c = chars[counter]; + switch (c) + { + case '<': + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + last = counter + 1; + + WriteAsBytes(OutputStream, "<".ToCharArray()); + break; + case '>': + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + last = counter + 1; + WriteAsBytes(OutputStream, ">".ToCharArray()); + break; + case '&': + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + last = counter + 1; + WriteAsBytes(OutputStream, "&".ToCharArray()); + break; + case '"': + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + last = counter + 1; + WriteAsBytes(OutputStream, """.ToCharArray()); + break; + // Special characters + case '\n': + case '\r': + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + WriteAsBytes(OutputStream, " ".ToCharArray()); + last = counter + 1; + break; + case '\t': + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + WriteAsBytes(OutputStream, " ".ToCharArray()); + last = counter + 1; + break; + case (char)0xa0: + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + WriteAsBytes(OutputStream, " ".ToCharArray()); + last = counter + 1; + break; + default: + // YK: XmlBeans silently replaces all ISO control characters ( < 32) with question marks. + // the same rule applies to unicode surrogates and "not a character" symbols. + if (c < ' ' || Char.IsLowSurrogate(c) || Char.IsHighSurrogate(c) || + ('\uFFFE' <= c && c <= '\uFFFF')) + { + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + WriteAsBytes(OutputStream, "?"); + last = counter + 1; + } + else if (c > 127) + { + if (counter > last) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, counter - last)); + } + last = counter + 1; + // If the character is outside of UTF8, write the + // numeric value. + WriteAsBytes(OutputStream, "&#".ToCharArray()); + WriteAsBytes(OutputStream, ((int)c).ToString()); + WriteAsBytes(OutputStream, ";"); + } + break; + } + } + if (last < length) + { + WriteAsBytes(OutputStream, GetSubArray(chars, last, length - last)); + } + } + + private char[] GetSubArray(char[] oldArray, int skip, int take) + { + var sub = new char[take]; + Array.Copy(oldArray, skip, sub, 0, take); + return sub; + } + + /** + * Deletes the temporary file that backed this sheet on disk. + * @return true if the file was deleted, false if it wasn't. + */ + public bool Dispose() + { + bool ret; + try + { + OutputStream.Close(); + } + finally + { + TemporaryFileInfo.Delete(); + ret = File.Exists(TemporaryFileInfo.FullName); + } + return ret; + } + + public string TemporaryFilePath() + { + if (TemporaryFileInfo != null) + { + return TemporaryFileInfo.FullName; + } + else + { + return string.Empty; + } + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/BlankValue.cs b/src/NPOI.OOXML/Streaming/Values/BlankValue.cs new file mode 100644 index 0000000..f721690 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/BlankValue.cs @@ -0,0 +1,29 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values + +{ + public class BlankValue : Value + { + CellType Value.GetType() + { + return CellType.Blank; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/BooleanFormulaValue.cs b/src/NPOI.OOXML/Streaming/Values/BooleanFormulaValue.cs new file mode 100644 index 0000000..0df4180 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/BooleanFormulaValue.cs @@ -0,0 +1,31 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class BooleanFormulaValue : FormulaValue + { + public bool PreEvaluatedValue { get; set; } + + public override CellType GetFormulaType() + { + return CellType.Boolean; + } + + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/BooleanValue.cs b/src/NPOI.OOXML/Streaming/Values/BooleanValue.cs new file mode 100644 index 0000000..7f1d256 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/BooleanValue.cs @@ -0,0 +1,30 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class BooleanValue : Value + { + public bool Value { get; set; } + public CellType GetType() + { + return CellType.Boolean; + } + + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/ErrorFormulaValue.cs b/src/NPOI.OOXML/Streaming/Values/ErrorFormulaValue.cs new file mode 100644 index 0000000..b818b1f --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/ErrorFormulaValue.cs @@ -0,0 +1,31 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class ErrorFormulaValue : FormulaValue + { + public byte PreEvaluatedValue; + + public override CellType GetFormulaType() + { + return CellType.Error; + } + + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/ErrorValue.cs b/src/NPOI.OOXML/Streaming/Values/ErrorValue.cs new file mode 100644 index 0000000..9188a02 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/ErrorValue.cs @@ -0,0 +1,30 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class ErrorValue : Value + { + public byte Value; + public CellType GetType() + { + return CellType.Error; + } + + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/FormulaValue.cs b/src/NPOI.OOXML/Streaming/Values/FormulaValue.cs new file mode 100644 index 0000000..70f10f8 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/FormulaValue.cs @@ -0,0 +1,31 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public abstract class FormulaValue : Value + { + public string Value; + public CellType GetType() + { + return CellType.Formula; + } + + public abstract CellType GetFormulaType(); + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/NumericFormulaValue.cs b/src/NPOI.OOXML/Streaming/Values/NumericFormulaValue.cs new file mode 100644 index 0000000..1eb2c2c --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/NumericFormulaValue.cs @@ -0,0 +1,30 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class NumericFormulaValue : FormulaValue + { + public double PreEvaluatedValue; + + public override CellType GetFormulaType() + { + return CellType.Numeric; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/NumericValue.cs b/src/NPOI.OOXML/Streaming/Values/NumericValue.cs new file mode 100644 index 0000000..aec4487 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/NumericValue.cs @@ -0,0 +1,29 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class NumericValue : Value + { + public double Value; + public CellType GetType() + { + return CellType.Numeric; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/PlainStringValue.cs b/src/NPOI.OOXML/Streaming/Values/PlainStringValue.cs new file mode 100644 index 0000000..f52d035 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/PlainStringValue.cs @@ -0,0 +1,28 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +namespace NPOI.XSSF.Streaming.Values +{ + public class PlainStringValue : StringValue + { + public string Value; + + public override bool IsRichText() + { + return false; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/RichTextValue.cs b/src/NPOI.OOXML/Streaming/Values/RichTextValue.cs new file mode 100644 index 0000000..33fe252 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/RichTextValue.cs @@ -0,0 +1,36 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class RichTextValue : StringValue + { + public IRichTextString Value; + + public CellType GetType() + { + return CellType.String; + } + + + public override bool IsRichText() + { + return true; + } + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/StringFormulaValue.cs b/src/NPOI.OOXML/Streaming/Values/StringFormulaValue.cs new file mode 100644 index 0000000..9756464 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/StringFormulaValue.cs @@ -0,0 +1,31 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public class StringFormulaValue : FormulaValue + { + public string PreEvaluatedValue; + + public override CellType GetFormulaType() + { + return CellType.String; + } + + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/StringValue.cs b/src/NPOI.OOXML/Streaming/Values/StringValue.cs new file mode 100644 index 0000000..f7dfae2 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/StringValue.cs @@ -0,0 +1,30 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public abstract class StringValue : Value + { + public CellType GetType() + { + return CellType.String; + } + //We cannot introduce a new type CellType.RICH_TEXT because the types are public so we have to make rich text as a type of string + public abstract bool IsRichText(); // using the POI style which seems to avoid "instanceof". + } +} diff --git a/src/NPOI.OOXML/Streaming/Values/Value.cs b/src/NPOI.OOXML/Streaming/Values/Value.cs new file mode 100644 index 0000000..a7b5ea6 --- /dev/null +++ b/src/NPOI.OOXML/Streaming/Values/Value.cs @@ -0,0 +1,25 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for Additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +using NPOI.SS.UserModel; + +namespace NPOI.XSSF.Streaming.Values +{ + public interface Value + { + CellType GetType(); + } +} diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFCell.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFCell.cs index a739828..81081e5 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFCell.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFCell.cs @@ -1153,6 +1153,11 @@ namespace NPOI.XSSF.UserModel { return CellUtil.CopyCell(this.Row, this.ColumnIndex, targetIndex); } + + public CellType GetCachedFormulaResultTypeEnum() + { + throw new NotImplementedException(); + } } diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationCell.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationCell.cs index 9f9bd7a..57665f5 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationCell.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationCell.cs @@ -45,6 +45,11 @@ namespace NPOI.XSSF.UserModel } + public XSSFEvaluationCell() + { + + } + public Object IdentityKey { get diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationSheet.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationSheet.cs index 3b4615e..b727217 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationSheet.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationSheet.cs @@ -35,6 +35,11 @@ namespace NPOI.XSSF.UserModel _xs = (XSSFSheet)sheet; } + public XSSFEvaluationSheet() + { + + } + public XSSFSheet GetXSSFSheet() { return _xs; diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationWorkbook.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationWorkbook.cs index ab8795e..b9b3e1e 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationWorkbook.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFEvaluationWorkbook.cs @@ -50,7 +50,7 @@ namespace NPOI.XSSF.UserModel return new XSSFEvaluationWorkbook(book); } - private XSSFEvaluationWorkbook(IWorkbook book) + protected XSSFEvaluationWorkbook(IWorkbook book) { _uBook = (XSSFWorkbook)book; } diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFFormulaEvaluator.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFFormulaEvaluator.cs index 28b38f1..e95fef1 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFFormulaEvaluator.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFFormulaEvaluator.cs @@ -49,6 +49,12 @@ namespace NPOI.XSSF.UserModel : this(workbook, null, null) { } + //TODO; will need testing added for streaming + public XSSFFormulaEvaluator(WorkbookEvaluator bookEvaluator) + { + _bookEvaluator = bookEvaluator; + } + /** * @param stabilityClassifier used to optimise caching performance. Pass null * for the (conservative) assumption that any cell may have its defInition Changed After diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFRichTextString.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFRichTextString.cs index f01aae0..54ce263 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFRichTextString.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFRichTextString.cs @@ -670,6 +670,22 @@ namespace NPOI.XSSF.UserModel if (styles == null) return null; return styles.GetTheme(); } + + public bool HasFormatting() + { + //noinspection deprecation - for performance reasons! + CT_RElt[] rs = st.r.ToArray(); + if (rs == null || rs.Length == 0) + { + return false; + } + foreach (CT_RElt r in rs) + { + //TODO: check that this functions the same. + if (r.rPr != null) return true; + } + return false; + } } } diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFRow.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFRow.cs index 55d7105..1b1b08b 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFRow.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFRow.cs @@ -641,6 +641,12 @@ namespace NPOI.XSSF.UserModel { return GetEnumerator(); } + + public bool HasCustomHeight() + { + throw new NotImplementedException(); + } + public int OutlineLevel { get @@ -648,6 +654,32 @@ namespace NPOI.XSSF.UserModel return _row.outlineLevel; } } + + public bool? Hidden + { + get + { + throw new NotImplementedException(); + } + + set + { + throw new NotImplementedException(); + } + } + + public bool? Collapsed + { + get + { + throw new NotImplementedException(); + } + + set + { + throw new NotImplementedException(); + } + } #endregion } diff --git a/src/NPOI/HSSF/UserModel/HSSFCell.cs b/src/NPOI/HSSF/UserModel/HSSFCell.cs index 8431873..5709439 100644 --- a/src/NPOI/HSSF/UserModel/HSSFCell.cs +++ b/src/NPOI/HSSF/UserModel/HSSFCell.cs @@ -1332,6 +1332,11 @@ namespace NPOI.HSSF.UserModel NotifyArrayFormulaChanging(msg); } + public CellType GetCachedFormulaResultTypeEnum() + { + throw new NotImplementedException(); + } + public bool IsMergedCell { get diff --git a/src/NPOI/HSSF/UserModel/HSSFRow.cs b/src/NPOI/HSSF/UserModel/HSSFRow.cs index 555917d..53ee489 100644 --- a/src/NPOI/HSSF/UserModel/HSSFRow.cs +++ b/src/NPOI/HSSF/UserModel/HSSFRow.cs @@ -713,6 +713,32 @@ namespace NPOI.HSSF.UserModel } } + public bool? Hidden + { + get + { + throw new NotImplementedException(); + } + + set + { + throw new NotImplementedException(); + } + } + + public bool? Collapsed + { + get + { + throw new NotImplementedException(); + } + + set + { + throw new NotImplementedException(); + } + } + /// /// Gets the cell enumerator of the physically defined cells. /// @@ -869,5 +895,10 @@ namespace NPOI.HSSF.UserModel { return GetEnumerator(); } + + public bool HasCustomHeight() + { + throw new NotImplementedException(); + } } } \ No newline at end of file diff --git a/src/NPOI/SS/UserModel/Cell.cs b/src/NPOI/SS/UserModel/Cell.cs index f888d2c..0d4cfe9 100644 --- a/src/NPOI/SS/UserModel/Cell.cs +++ b/src/NPOI/SS/UserModel/Cell.cs @@ -246,6 +246,8 @@ namespace NPOI.SS.UserModel bool IsPartOfArrayFormulaGroup { get; } bool IsMergedCell { get; } + + CellType GetCachedFormulaResultTypeEnum(); } } diff --git a/src/NPOI/SS/UserModel/Row.cs b/src/NPOI/SS/UserModel/Row.cs index eced288..501dbb5 100644 --- a/src/NPOI/SS/UserModel/Row.cs +++ b/src/NPOI/SS/UserModel/Row.cs @@ -28,16 +28,31 @@ namespace NPOI.SS.UserModel { private static int NEXT_ID = 1; public int id; + public Policy _policy; public MissingCellPolicy() { this.id = NEXT_ID++; } + + public MissingCellPolicy(Policy policy) + { + this.id = NEXT_ID++; + _policy = policy; + + } /// Missing cells are returned as null, Blank cells are returned as normal public static readonly MissingCellPolicy RETURN_NULL_AND_BLANK = new MissingCellPolicy(); /// Missing cells are returned as null, as are blank cells public static readonly MissingCellPolicy RETURN_BLANK_AS_NULL = new MissingCellPolicy(); /// A new, blank cell is Created for missing cells. Blank cells are returned as normal public static readonly MissingCellPolicy CREATE_NULL_AS_BLANK = new MissingCellPolicy(); + + public enum Policy + { + RETURN_NULL_AND_BLANK = 1, + RETURN_BLANK_AS_NULL = 2, + CREATE_NULL_AS_BLANK = 3 + } } /// @@ -216,6 +231,12 @@ namespace NPOI.SS.UserModel /// you take it out of them. /// int OutlineLevel { get; } + + bool HasCustomHeight(); + + bool? Hidden { get; set; } + + bool? Collapsed { get; set; } } } diff --git a/src/NPOI/SS/Util/SheetUtil.cs b/src/NPOI/SS/Util/SheetUtil.cs index a5b16aa..2c957b4 100644 --- a/src/NPOI/SS/Util/SheetUtil.cs +++ b/src/NPOI/SS/Util/SheetUtil.cs @@ -661,5 +661,17 @@ namespace NPOI.SS.Util return null; } + public static int getDefaultCharWidth(IWorkbook wb) + { + //TODO: Implement! + return 1; + //throw new NotImplementedException(); + //IFont defaultFont = wb.GetFontAt(0); + + //IAttributedString str = new AttributedString(defaultChar.ToString()); + //copyAttributes(defaultFont, str, 0, 1); + //ITextLayout layout = new TextLayout(str.getIterator(), fontRenderContext); + //return (int)layout.getAdvance(); + } } } diff --git a/src/NPOI/Util/Character.cs b/src/NPOI/Util/Character.cs index 05bd17f..f4c9226 100644 --- a/src/NPOI/Util/Character.cs +++ b/src/NPOI/Util/Character.cs @@ -18,5 +18,11 @@ } return -1; } + + //TODO: this should work but maybe not. + public static bool isWhitespace(char src) + { + return char.IsWhiteSpace(src); + } } } From fe14c3f38978a398bc83973d04a21618b2ccd2ed Mon Sep 17 00:00:00 2001 From: Jie Date: Mon, 21 May 2018 13:16:03 +0800 Subject: [PATCH 02/38] =?UTF-8?q?fix=20CopyRow=20bugs:=201.=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=9B=AE=E6=A0=87=E4=BD=8D=E7=BD=AE=E6=9C=89row?= =?UTF-8?q?=E6=97=B6=E4=B8=8D=E5=88=9B=E5=BB=BA=E6=96=B0=E8=A1=8C=E7=9A=84?= =?UTF-8?q?bug=E3=80=82=202.=E4=BF=AE=E5=A4=8D=E7=A7=BB=E5=8A=A8=E8=A1=8C?= =?UTF-8?q?=E8=A1=8C=E9=AB=98=E8=A2=AB=E9=87=8D=E7=BD=AE=E7=9A=84bug?= =?UTF-8?q?=E3=80=82=203.=E4=BF=AE=E5=A4=8D=E6=96=B0=E8=A1=8C=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E5=A4=8D=E5=88=B6=E5=8E=9F=E8=A1=8C=E9=AB=98=E5=BA=A6?= =?UTF-8?q?=E7=9A=84bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/NPOI/SS/Util/SheetUtil.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/NPOI/SS/Util/SheetUtil.cs b/src/NPOI/SS/Util/SheetUtil.cs index a5b16aa..523f52d 100644 --- a/src/NPOI/SS/Util/SheetUtil.cs +++ b/src/NPOI/SS/Util/SheetUtil.cs @@ -170,7 +170,7 @@ namespace NPOI.SS.Util targetSheet.AddMergedRegion(newCellRangeAddress); } } - return newRow; + return newRow; } public static IRow CopyRow(ISheet sheet, int sourceRowIndex, int targetRowIndex) { @@ -183,12 +183,12 @@ namespace NPOI.SS.Util // If the row exist in destination, push down all rows by 1 else create a new row if (newRow != null) { - sheet.ShiftRows(targetRowIndex, sheet.LastRowNum, 1); - } - else - { - newRow = sheet.CreateRow(targetRowIndex); + sheet.ShiftRows(targetRowIndex, sheet.LastRowNum, 1, true, false); } + //new row + newRow = sheet.CreateRow(targetRowIndex); + //copyHeight + newRow.Height = sourceRow.Height; // Loop through source columns to add to new row for (int i = sourceRow.FirstCellNum; i < sourceRow.LastCellNum; i++) @@ -312,7 +312,7 @@ namespace NPOI.SS.Util //TextLayout layout; double width = -1; - using (Bitmap bmp = new Bitmap(1,1)) + using (Bitmap bmp = new Bitmap(1, 1)) using (Graphics g = Graphics.FromImage(bmp)) { if (cellType == CellType.String) @@ -450,7 +450,7 @@ namespace NPOI.SS.Util IWorkbook wb = sheet.Workbook; DataFormatter formatter = new DataFormatter(); - IFont defaultFont = wb.GetFontAt((short) 0); + IFont defaultFont = wb.GetFontAt((short)0); //str = new AttributedString((defaultChar)); //copyAttributes(defaultFont, str, 0, 1); From e38e51fc2c105de45d103779cc7942788ef9c409 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 19 Jul 2018 22:12:09 +0800 Subject: [PATCH 03/38] upgrade dependent nuget packages. --- src/NPOI/NPOI.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NPOI/NPOI.csproj b/src/NPOI/NPOI.csproj index fd16c16..8912957 100644 --- a/src/NPOI/NPOI.csproj +++ b/src/NPOI/NPOI.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -19,9 +19,9 @@ - - - + + + From 09a0de0f268ab987a6c2b42e7cbb15f58d1095c7 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 19 Jul 2018 22:13:33 +0800 Subject: [PATCH 04/38] replace ZKWeb.System.Drawing to System.Drawing.Common --- src/NPOI/DDF/EscherMetafileBlip.cs | 2 +- src/NPOI/DDF/EscherPictBlip.cs | 2 +- src/NPOI/HSSF/UserModel/EscherGraphics.cs | 2 +- src/NPOI/HSSF/UserModel/HSSFPicture.cs | 2 +- src/NPOI/HSSF/UserModel/HSSFSheet.cs | 2 +- src/NPOI/HSSF/UserModel/StaticFontMetrics.cs | 2 +- src/NPOI/Label.cs | 2 +- src/NPOI/SS/Format/CellFormat.cs | 2 +- src/NPOI/SS/Format/CellFormatPart.cs | 2 +- src/NPOI/SS/Format/CellFormatResult.cs | 2 +- src/NPOI/SS/UserModel/Picture.cs | 2 +- src/NPOI/SS/Util/ImageUtils.cs | 2 +- src/NPOI/SS/Util/SheetUtil.cs | 2 +- src/NPOI/TextRenderer.cs | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/NPOI/DDF/EscherMetafileBlip.cs b/src/NPOI/DDF/EscherMetafileBlip.cs index 21e8e32..3dea7cb 100644 --- a/src/NPOI/DDF/EscherMetafileBlip.cs +++ b/src/NPOI/DDF/EscherMetafileBlip.cs @@ -19,7 +19,7 @@ namespace NPOI.DDF using System; using System.IO; using System.Text; - using System.DrawingCore; + using System.Drawing; using NPOI.Util; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using ICSharpCode.SharpZipLib.Zip.Compression; diff --git a/src/NPOI/DDF/EscherPictBlip.cs b/src/NPOI/DDF/EscherPictBlip.cs index 1402588..1a51f44 100644 --- a/src/NPOI/DDF/EscherPictBlip.cs +++ b/src/NPOI/DDF/EscherPictBlip.cs @@ -19,7 +19,7 @@ namespace NPOI.DDF using System; using System.IO; using System.Text; - using System.DrawingCore; + using System.Drawing; using NPOI.Util; using ICSharpCode.SharpZipLib.Zip.Compression; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; diff --git a/src/NPOI/HSSF/UserModel/EscherGraphics.cs b/src/NPOI/HSSF/UserModel/EscherGraphics.cs index de0a1da..2e7888f 100644 --- a/src/NPOI/HSSF/UserModel/EscherGraphics.cs +++ b/src/NPOI/HSSF/UserModel/EscherGraphics.cs @@ -22,7 +22,7 @@ namespace NPOI.HSSF.UserModel using NPOI.Util; using NPOI.SS.UserModel; - using System.DrawingCore; + using System.Drawing; /** * Translates Graphics calls into escher calls. The translation Is lossy so diff --git a/src/NPOI/HSSF/UserModel/HSSFPicture.cs b/src/NPOI/HSSF/UserModel/HSSFPicture.cs index 8443101..055d2d0 100644 --- a/src/NPOI/HSSF/UserModel/HSSFPicture.cs +++ b/src/NPOI/HSSF/UserModel/HSSFPicture.cs @@ -26,7 +26,7 @@ namespace NPOI.HSSF.UserModel using NPOI.HSSF.Model; using NPOI.HSSF.Record; using NPOI.SS.Util; - using System.DrawingCore; + using System.Drawing; /// diff --git a/src/NPOI/HSSF/UserModel/HSSFSheet.cs b/src/NPOI/HSSF/UserModel/HSSFSheet.cs index 3abaada..7c13232 100644 --- a/src/NPOI/HSSF/UserModel/HSSFSheet.cs +++ b/src/NPOI/HSSF/UserModel/HSSFSheet.cs @@ -32,7 +32,7 @@ namespace NPOI.HSSF.UserModel using NPOI.SS.UserModel; using NPOI.SS.Util; using System.Globalization; - using System.DrawingCore; + using System.Drawing; diff --git a/src/NPOI/HSSF/UserModel/StaticFontMetrics.cs b/src/NPOI/HSSF/UserModel/StaticFontMetrics.cs index 61504c8..b5b7f6b 100644 --- a/src/NPOI/HSSF/UserModel/StaticFontMetrics.cs +++ b/src/NPOI/HSSF/UserModel/StaticFontMetrics.cs @@ -20,7 +20,7 @@ namespace NPOI.HSSF.UserModel using System; using System.Collections; using System.IO; - using System.DrawingCore; + using System.Drawing; using System.Configuration; using NPOI.Util.Collections; using System.Resources; diff --git a/src/NPOI/Label.cs b/src/NPOI/Label.cs index c96a054..36f362e 100644 --- a/src/NPOI/Label.cs +++ b/src/NPOI/Label.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Text; -using System.DrawingCore; +using System.Drawing; namespace System.Windows.Forms { diff --git a/src/NPOI/SS/Format/CellFormat.cs b/src/NPOI/SS/Format/CellFormat.cs index 5577f40..73d7255 100644 --- a/src/NPOI/SS/Format/CellFormat.cs +++ b/src/NPOI/SS/Format/CellFormat.cs @@ -23,7 +23,7 @@ namespace NPOI.SS.Format using System.Text.RegularExpressions; using System.Collections.Generic; using System.Windows.Forms; - using System.DrawingCore; + using System.Drawing; /** * Format a value according to the standard Excel behavior. This "standard" is diff --git a/src/NPOI/SS/Format/CellFormatPart.cs b/src/NPOI/SS/Format/CellFormatPart.cs index 9048d48..d1bea03 100644 --- a/src/NPOI/SS/Format/CellFormatPart.cs +++ b/src/NPOI/SS/Format/CellFormatPart.cs @@ -20,7 +20,7 @@ namespace NPOI.SS.Format using NPOI.HSSF.Util; using System.Collections.Generic; - using System.DrawingCore; + using System.Drawing; using System.Collections; using System.Text.RegularExpressions; using System.Text; diff --git a/src/NPOI/SS/Format/CellFormatResult.cs b/src/NPOI/SS/Format/CellFormatResult.cs index 65d4392..9f55abc 100644 --- a/src/NPOI/SS/Format/CellFormatResult.cs +++ b/src/NPOI/SS/Format/CellFormatResult.cs @@ -17,7 +17,7 @@ namespace NPOI.SS.Format { using System; - using System.DrawingCore; + using System.Drawing; diff --git a/src/NPOI/SS/UserModel/Picture.cs b/src/NPOI/SS/UserModel/Picture.cs index 06aa8a8..b7bcff8 100644 --- a/src/NPOI/SS/UserModel/Picture.cs +++ b/src/NPOI/SS/UserModel/Picture.cs @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ -using System.DrawingCore; +using System.Drawing; namespace NPOI.SS.UserModel { public enum PictureType : int diff --git a/src/NPOI/SS/Util/ImageUtils.cs b/src/NPOI/SS/Util/ImageUtils.cs index 134e90a..ece12ec 100644 --- a/src/NPOI/SS/Util/ImageUtils.cs +++ b/src/NPOI/SS/Util/ImageUtils.cs @@ -17,7 +17,7 @@ namespace NPOI.SS.Util { using System; - using System.DrawingCore; + using System.Drawing; using System.IO; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; diff --git a/src/NPOI/SS/Util/SheetUtil.cs b/src/NPOI/SS/Util/SheetUtil.cs index a5b16aa..87044ca 100644 --- a/src/NPOI/SS/Util/SheetUtil.cs +++ b/src/NPOI/SS/Util/SheetUtil.cs @@ -20,7 +20,7 @@ namespace NPOI.SS.Util using System; using NPOI.SS.UserModel; - using System.DrawingCore; + using System.Drawing; using System.Windows.Forms; using System.Collections.Generic; diff --git a/src/NPOI/TextRenderer.cs b/src/NPOI/TextRenderer.cs index 4bb54e8..7707075 100644 --- a/src/NPOI/TextRenderer.cs +++ b/src/NPOI/TextRenderer.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.DrawingCore; +using System.Drawing; using System.Text; namespace System.Windows.Forms From 9f952aacebfb4f45e2d916bae35e8ee15667f6e9 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 19 Jul 2018 23:09:45 +0800 Subject: [PATCH 05/38] replace ZKWeb.System.Drawing to System.Drawing.Common --- src/NPOI.OOXML/SS/UserModel/IndexedColors.cs | 2 +- src/NPOI.OOXML/XSSF/UserModel/XSSFColor.cs | 2 +- src/NPOI.OOXML/XSSF/UserModel/XSSFPicture.cs | 2 +- src/NPOI.OOXML/XSSF/UserModel/XSSFTextParagraph.cs | 2 +- src/NPOI.OOXML/XSSF/UserModel/XSSFTextRun.cs | 2 +- test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFCellStyle.cs | 2 +- test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFDrawing.cs | 2 +- .../NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFSimpleShape.cs | 2 +- .../XSSF/UserModel/TestXSSFTextParagraph.cs | 2 +- test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextRun.cs | 2 +- test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs | 4 ++-- test/NPOI.TestCases/HSSF/UserModel/TestHSSFPictureData.cs | 4 ++-- test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs | 2 +- test/NPOI.TestCases/SS/UserModel/BaseTestPicture.cs | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs b/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs index a45ba36..ea08bdf 100644 --- a/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs +++ b/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs @@ -18,7 +18,7 @@ using NPOI.HSSF.Util; using NPOI.XSSF.UserModel; using System.Collections.Generic; -using System.DrawingCore; +using System.Drawing; using System.Text; namespace NPOI.SS.UserModel { diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFColor.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFColor.cs index 972ea19..58a9222 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFColor.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFColor.cs @@ -21,7 +21,7 @@ using System.Text; using NPOI.Util; using NPOI.SS.UserModel; using NPOI.OpenXmlFormats.Spreadsheet; -using System.DrawingCore; +using System.Drawing; namespace NPOI.XSSF.UserModel { diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFPicture.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFPicture.cs index 9514e6f..6a2ac62 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFPicture.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFPicture.cs @@ -16,7 +16,7 @@ ==================================================================== */ using System; -using System.DrawingCore; +using System.Drawing; using System.IO; using NPOI.OpenXml4Net.OPC; using NPOI.OpenXmlFormats.Dml; diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFTextParagraph.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFTextParagraph.cs index 8762355..8f04482 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFTextParagraph.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFTextParagraph.cs @@ -20,7 +20,7 @@ using NPOI.OpenXmlFormats.Dml.Spreadsheet; using System; using System.Text; using NPOI.XSSF.Model; -using System.DrawingCore; +using System.Drawing; using NPOI.Util; namespace NPOI.XSSF.UserModel { diff --git a/src/NPOI.OOXML/XSSF/UserModel/XSSFTextRun.cs b/src/NPOI.OOXML/XSSF/UserModel/XSSFTextRun.cs index ff1beda..4f30e33 100644 --- a/src/NPOI.OOXML/XSSF/UserModel/XSSFTextRun.cs +++ b/src/NPOI.OOXML/XSSF/UserModel/XSSFTextRun.cs @@ -16,7 +16,7 @@ ==================================================================== */ using System; using NPOI.OpenXmlFormats.Dml; -using System.DrawingCore; +using System.Drawing; using NPOI.Util; namespace NPOI.XSSF.UserModel { diff --git a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFCellStyle.cs b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFCellStyle.cs index 0771f48..efebb32 100644 --- a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFCellStyle.cs +++ b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFCellStyle.cs @@ -21,7 +21,7 @@ using NPOI.XSSF.UserModel.Extensions; using NUnit.Framework; using NPOI.SS.UserModel; using NPOI.HSSF.UserModel; -using System.DrawingCore; +using System.Drawing; using NPOI.HSSF.Util; namespace NPOI.XSSF.UserModel { diff --git a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFDrawing.cs b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFDrawing.cs index 4fb9795..65464b8 100644 --- a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFDrawing.cs +++ b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFDrawing.cs @@ -21,7 +21,7 @@ using NPOI.OpenXml4Net.OPC; using NPOI.SS.UserModel; using NPOI.OpenXmlFormats.Dml; using NPOI.Util; -using System.DrawingCore; +using System.Drawing; using NPOI.OpenXmlFormats.Dml.Spreadsheet; using System.Text; namespace NPOI.XSSF.UserModel diff --git a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFSimpleShape.cs b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFSimpleShape.cs index c2c43df..5d03272 100644 --- a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFSimpleShape.cs +++ b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFSimpleShape.cs @@ -19,7 +19,7 @@ namespace NPOI.XSSF.UserModel using System; using NPOI.SS.UserModel; using NUnit.Framework; - using System.DrawingCore; + using System.Drawing; [TestFixture] diff --git a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextParagraph.cs b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextParagraph.cs index b1cdb5c..d0acbfe 100644 --- a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextParagraph.cs +++ b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextParagraph.cs @@ -18,7 +18,7 @@ namespace NPOI.XSSF.UserModel { using System; using NUnit.Framework; - using System.DrawingCore; + using System.Drawing; using System.Collections.Generic; [TestFixture] diff --git a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextRun.cs b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextRun.cs index dac01ff..8f6dde6 100644 --- a/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextRun.cs +++ b/test/NPOI.OpenXmlFormats/XSSF/UserModel/TestXSSFTextRun.cs @@ -19,7 +19,7 @@ namespace NPOI.XSSF.UserModel using System; using NUnit.Framework; using System.Collections.Generic; - using System.DrawingCore; + using System.Drawing; [TestFixture] public class TestXSSFTextRun { diff --git a/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs b/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs index 577ddbb..503b07c 100644 --- a/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs +++ b/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs @@ -19,8 +19,8 @@ namespace TestCases.HSSF.UserModel { using System; using System.IO; - using System.DrawingCore; - using System.DrawingCore.Drawing2D; + using System.Drawing; + using System.Drawing.Drawing2D; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; diff --git a/test/NPOI.TestCases/HSSF/UserModel/TestHSSFPictureData.cs b/test/NPOI.TestCases/HSSF/UserModel/TestHSSFPictureData.cs index abc9748..8ddd3cf 100644 --- a/test/NPOI.TestCases/HSSF/UserModel/TestHSSFPictureData.cs +++ b/test/NPOI.TestCases/HSSF/UserModel/TestHSSFPictureData.cs @@ -24,8 +24,8 @@ namespace TestCases.HSSF.UserModel using NUnit.Framework; using System.IO; using TestCases.HSSF; - using System.DrawingCore; - using System.DrawingCore.Imaging; + using System.Drawing; + using System.Drawing.Imaging; using NPOI.SS.UserModel; using System.Collections.Generic; diff --git a/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs b/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs index ec90899..6aea42d 100644 --- a/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs +++ b/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs @@ -19,7 +19,7 @@ namespace TestCases.SS.Format using System; using System.Collections; using System.Collections.Generic; - using System.DrawingCore; + using System.Drawing; using System.Text.RegularExpressions; using System.Windows.Forms; using NUnit.Framework; diff --git a/test/NPOI.TestCases/SS/UserModel/BaseTestPicture.cs b/test/NPOI.TestCases/SS/UserModel/BaseTestPicture.cs index c380261..167ace4 100644 --- a/test/NPOI.TestCases/SS/UserModel/BaseTestPicture.cs +++ b/test/NPOI.TestCases/SS/UserModel/BaseTestPicture.cs @@ -17,7 +17,7 @@ using NPOI.SS.UserModel; using NUnit.Framework; -using System.DrawingCore; +using System.Drawing; using NPOI.Util; using NPOI.SS.Util; using System.IO; From 8b6dc0e2bff9d06b5b9e23b980c2eafe55be8b29 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 19 Jul 2018 23:12:04 +0800 Subject: [PATCH 06/38] Re-Support .NET Framework 4.6.1. (#68) --- src/NPOI.OOXML/NPOI.OOXML.csproj | 9 ++------- src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj | 9 ++------- src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj | 6 +++--- src/NPOI/NPOI.csproj | 2 +- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/NPOI.OOXML/NPOI.OOXML.csproj b/src/NPOI.OOXML/NPOI.OOXML.csproj index 15fc623..2c8bf35 100644 --- a/src/NPOI.OOXML/NPOI.OOXML.csproj +++ b/src/NPOI.OOXML/NPOI.OOXML.csproj @@ -1,14 +1,9 @@ - + - netstandard2.0 + netstandard2.0;net461 - - - - - diff --git a/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj b/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj index 4f55d80..d4035aa 100644 --- a/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj +++ b/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj @@ -1,14 +1,9 @@ - + - netstandard2.0 + netstandard2.0;net461 - - - - - diff --git a/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj b/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj index 6be9312..509d34f 100644 --- a/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj +++ b/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj @@ -1,8 +1,8 @@ - + - netstandard2.0 - + netstandard2.0;net461 + diff --git a/src/NPOI/NPOI.csproj b/src/NPOI/NPOI.csproj index 8912957..a5eeaaf 100644 --- a/src/NPOI/NPOI.csproj +++ b/src/NPOI/NPOI.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;net461 From 82982d2377beda03287bd7d0476bce8ef96dc39a Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 19 Jul 2018 23:12:36 +0800 Subject: [PATCH 07/38] Fix some compilation errors for unit tests --- DotNetCore.NPOI.sln | 24 +++--- .../NPOI.OOXML4Net.Testcases.csproj | 51 +++-------- test/NPOI.OpenXml4Net/TestListParts.cs | 2 +- test/NPOI.OpenXml4Net/TestRelationships.cs | 9 +- test/NPOI.OpenXml4Net/packages.config | 14 +--- .../NPOI.OOXML.TestCases.csproj | 78 ++++------------- test/NPOI.OpenXmlFormats/packages.config | 17 +--- test/NPOI.TestCases/NPOI.TestCases.csproj | 84 ++----------------- test/NPOI.TestCases/packages.config | 15 +--- 9 files changed, 55 insertions(+), 239 deletions(-) diff --git a/DotNetCore.NPOI.sln b/DotNetCore.NPOI.sln index 4eacd0c..e9b0934 100644 --- a/DotNetCore.NPOI.sln +++ b/DotNetCore.NPOI.sln @@ -74,34 +74,34 @@ Global {4D994508-5489-4342-9EE8-6FDDB0763E66}.NPOI.Tools|Any CPU.Build.0 = Debug|Any CPU {4D994508-5489-4342-9EE8-6FDDB0763E66}.Release|Any CPU.ActiveCfg = Release|Any CPU {4D994508-5489-4342-9EE8-6FDDB0763E66}.Release|Any CPU.Build.0 = Release|Any CPU - {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 2 Release|Any CPU.ActiveCfg = .net 2 Release|Any CPU - {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 2 Release|Any CPU.Build.0 = .net 2 Release|Any CPU + {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 2 Release|Any CPU.ActiveCfg = Release|Any CPU + {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 2 Release|Any CPU.Build.0 = Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 4 Release|Any CPU.ActiveCfg = .net 4 Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 4 Release|Any CPU.Build.0 = .net 4 Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.NPOI.Tools|Any CPU.ActiveCfg = .net 2 Release|Any CPU - {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.NPOI.Tools|Any CPU.Build.0 = .net 2 Release|Any CPU + {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.NPOI.Tools|Any CPU.ActiveCfg = Release|Any CPU + {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.NPOI.Tools|Any CPU.Build.0 = Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.Release|Any CPU.Build.0 = Release|Any CPU - {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 2 Release|Any CPU.ActiveCfg = .net 2 Release|Any CPU - {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 2 Release|Any CPU.Build.0 = .net 2 Release|Any CPU - {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 4 Release|Any CPU.ActiveCfg = .net 4 Release|Any CPU - {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 4 Release|Any CPU.Build.0 = .net 4 Release|Any CPU + {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 2 Release|Any CPU.ActiveCfg = Release|Any CPU + {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 2 Release|Any CPU.Build.0 = Release|Any CPU + {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 4 Release|Any CPU.ActiveCfg = Release|Any CPU + {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 4 Release|Any CPU.Build.0 = Release|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Debug|Any CPU.Build.0 = Debug|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.NPOI.Tools|Any CPU.ActiveCfg = NPOI.Tools|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.NPOI.Tools|Any CPU.Build.0 = NPOI.Tools|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Release|Any CPU.Build.0 = Release|Any CPU - {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 2 Release|Any CPU.ActiveCfg = .net 2 Release|Any CPU - {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 2 Release|Any CPU.Build.0 = .net 2 Release|Any CPU + {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 2 Release|Any CPU.ActiveCfg = Release|Any CPU + {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 2 Release|Any CPU.Build.0 = Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 4 Release|Any CPU.ActiveCfg = .net 4 Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 4 Release|Any CPU.Build.0 = .net 4 Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.NPOI.Tools|Any CPU.ActiveCfg = .net 2 Release|Any CPU - {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.NPOI.Tools|Any CPU.Build.0 = .net 2 Release|Any CPU + {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.NPOI.Tools|Any CPU.ActiveCfg = Release|Any CPU + {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.NPOI.Tools|Any CPU.Build.0 = Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.Release|Any CPU.ActiveCfg = Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.Release|Any CPU.Build.0 = Release|Any CPU {4D493C32-B246-4DB5-B0DF-9AF3B63C230D}..net 2 Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj b/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj index b587dea..76349ec 100644 --- a/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj +++ b/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj @@ -1,5 +1,6 @@  + Debug AnyCPU @@ -32,7 +33,8 @@ false false true - + + true @@ -66,29 +68,14 @@ AllRules.ruleset false - - ..\..\solution\Lib\.net4\ - TRACE - true - pdbonly - AnyCPU - prompt - AllRules.ruleset - false - - - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll + + ..\..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll - - - - ..\..\packages\ZKWeb.System.Drawing.3.0.0\lib\net45\ZKWeb.System.Drawing.dll - @@ -112,28 +99,6 @@ Designer - - - False - Microsoft .NET Framework 4 %28x86 和 x64%29 - true - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - @@ -156,6 +121,12 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/test/NPOI.TestCases/packages.config b/test/NPOI.TestCases/packages.config index ad0b188..ebeb58f 100644 --- a/test/NPOI.TestCases/packages.config +++ b/test/NPOI.TestCases/packages.config @@ -1,17 +1,4 @@  - - - - - - - - - - - - - - + \ No newline at end of file From a824a2b4888996c260527a9a40f7f20e03445720 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 19 Jul 2018 23:23:16 +0800 Subject: [PATCH 08/38] update samples. --- .../Npoi.Samples.CreateNewSpreadsheet.csproj | 8 +------- .../Program.cs | 6 ++---- .../Properties/AssemblyInfo.cs | 19 ------------------- 3 files changed, 3 insertions(+), 30 deletions(-) delete mode 100644 samples/Npoi.Samples.CreateNewSpreadsheet/Properties/AssemblyInfo.cs diff --git a/samples/Npoi.Samples.CreateNewSpreadsheet/Npoi.Samples.CreateNewSpreadsheet.csproj b/samples/Npoi.Samples.CreateNewSpreadsheet/Npoi.Samples.CreateNewSpreadsheet.csproj index 1ed3649..22df917 100644 --- a/samples/Npoi.Samples.CreateNewSpreadsheet/Npoi.Samples.CreateNewSpreadsheet.csproj +++ b/samples/Npoi.Samples.CreateNewSpreadsheet/Npoi.Samples.CreateNewSpreadsheet.csproj @@ -1,15 +1,9 @@  - netcoreapp2.0 + netcoreapp2.1 Npoi.Samples.CreateNewSpreadsheet Exe - Npoi.Samples.CreateNewSpreadsheet - 2.0.0 - $(PackageTargetFallback);dnxcore50 - false - false - false diff --git a/samples/Npoi.Samples.CreateNewSpreadsheet/Program.cs b/samples/Npoi.Samples.CreateNewSpreadsheet/Program.cs index 69c184e..9966e47 100644 --- a/samples/Npoi.Samples.CreateNewSpreadsheet/Program.cs +++ b/samples/Npoi.Samples.CreateNewSpreadsheet/Program.cs @@ -13,12 +13,10 @@ namespace Npoi.Samples.CreateNewSpreadsheet public class Program { public static void Main(string[] args) { - //ExportExcel(); + ExportExcel(); //ExportExcelHSSF(); - //ExportWord(); + ExportWord(); //ImportExcelHSSF(); - Issue32.Run(); - Console.Read(); } private static void ImportExcelHSSF() { diff --git a/samples/Npoi.Samples.CreateNewSpreadsheet/Properties/AssemblyInfo.cs b/samples/Npoi.Samples.CreateNewSpreadsheet/Properties/AssemblyInfo.cs deleted file mode 100644 index c4f09d0..0000000 --- a/samples/Npoi.Samples.CreateNewSpreadsheet/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Npoi.Samples.CreateNewSpreadsheet")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("e26bbd8a-3a38-4f82-91a4-7f81ecfb8196")] From 6b51bad96360c2ed4977e0a3d03f8ba57072bf58 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 19 Jul 2018 23:32:35 +0800 Subject: [PATCH 09/38] add Alpine dockerfile remarks about libgdiplus. (#69) --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 3d46119..9b1eaff 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,15 @@ On Linux, you need install `libgdiplus`. - cd /usr/lib64/ - ln -s /usr/local/lib/libgdiplus.so gdiplus.dll +- Docker + - Alpine + ``` + # base sdk-alpine/aspnetcore-runtime-alpine images + + RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories + RUN apk --update add libgdiplus + ``` + ### Getting Started #### Export Excel From 6eaa305b95af109d8508083547032135ae510296 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Fri, 20 Jul 2018 00:29:51 +0800 Subject: [PATCH 10/38] add ci support. --- Directory.Build.props | 18 +++ DotNetCore.NPOI.sln | 8 ++ README.md | 2 + appveyor.yml | 14 +++ build.cake | 101 +++++++++++++++++ build.ps1 | 183 +++++++++++++++++++++++++++++++ build/index.cake | 2 + build/util.cake | 25 +++++ build/version.cake | 120 ++++++++++++++++++++ build/version.props | 9 ++ src/NPOI.OOXML/NPOI.OOXML.csproj | 17 +-- 11 files changed, 491 insertions(+), 8 deletions(-) create mode 100644 Directory.Build.props create mode 100644 appveyor.yml create mode 100644 build.cake create mode 100644 build.ps1 create mode 100644 build/index.cake create mode 100644 build/util.cake create mode 100644 build/version.cake create mode 100644 build/version.props diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..542e807 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,18 @@ + + + + + + NPOI + .NET Core Community;Savorboard + https://github.com/dotnetcore/NPOI + git + $(MSBuildThisFileDirectory) + https://avatars2.githubusercontent.com/u/19404084 + https://github.com/dotnetcore/NPOI + https://github.com/dotnetcore/NPOI/blob/master/LICENSE.txt + NPOI,Office,Excel,Word + A .NET library for reading and writing Microsoft Office binary and OOXML file formats. + + + \ No newline at end of file diff --git a/DotNetCore.NPOI.sln b/DotNetCore.NPOI.sln index e9b0934..d1a763f 100644 --- a/DotNetCore.NPOI.sln +++ b/DotNetCore.NPOI.sln @@ -25,6 +25,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{2961 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Npoi.Samples.CreateNewSpreadsheet", "samples\Npoi.Samples.CreateNewSpreadsheet\Npoi.Samples.CreateNewSpreadsheet.csproj", "{4D493C32-B246-4DB5-B0DF-9AF3B63C230D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Itmes", "Solution Itmes", "{ADC5679E-5CFE-4D97-9F77-FB7FD9E65C55}" + ProjectSection(SolutionItems) = preProject + appveyor.yml = appveyor.yml + Directory.Build.props = Directory.Build.props + README.md = README.md + build\version.props = build\version.props + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution .net 2 Release|Any CPU = .net 2 Release|Any CPU diff --git a/README.md b/README.md index 9b1eaff..ae9621b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ ### NPOI +[![Build status](https://ci.appveyor.com/api/projects/status/k774la3yfxf0yfv8?svg=true)](https://ci.appveyor.com/project/yuleyule66/npoi) + This project is migrated from Tony Qu's [NPOI](https://github.com/tonyqus/npoi) by DotNETCore team. ### NPOI of .net standard here, NPOI elsewhere diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..df615df --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,14 @@ +version: '{build}' +os: Visual Studio 2017 +branches: + only: + - master +environment: + BUILDING_ON_PLATFORM: win + BuildEnvironment: appveyor +skip_commits: + files: + - LICENSE +build_script: +- ps: ./build.ps1 +test: off \ No newline at end of file diff --git a/build.cake b/build.cake new file mode 100644 index 0000000..5255382 --- /dev/null +++ b/build.cake @@ -0,0 +1,101 @@ +#addin "nuget:https://www.nuget.org/api/v2?package=Newtonsoft.Json&version=9.0.1" + +#load "./build/index.cake" + +var target = Argument("target", "Default"); + +var build = BuildParameters.Create(Context); +var util = new Util(Context, build); + +Task("Clean") + .Does(() => +{ + if (DirectoryExists("./artifacts")) + { + DeleteDirectory("./artifacts", true); + } +}); + +Task("Restore") + .IsDependentOn("Clean") + .Does(() => +{ + var settings = new DotNetCoreRestoreSettings + { + ArgumentCustomization = args => + { + args.Append($"/p:VersionSuffix={build.Version.Suffix}"); + return args; + } + }; + DotNetCoreRestore(settings); +}); + +Task("Build") + .IsDependentOn("Restore") + .Does(() => +{ + var settings = new DotNetCoreBuildSettings + { + Configuration = build.Configuration, + VersionSuffix = build.Version.Suffix, + ArgumentCustomization = args => + { + args.Append($"/p:InformationalVersion={build.Version.VersionWithSuffix()}"); + return args; + } + }; + foreach (var project in build.ProjectFiles) + { + DotNetCoreBuild(project.FullPath, settings); + } +}); + +Task("Test") + .IsDependentOn("Build") + .Does(() => +{ + foreach (var testProject in build.TestProjectFiles) + { + DotNetCoreTest(testProject.FullPath); + } +}); + +Task("Pack") + .Does(() => +{ + var settings = new DotNetCorePackSettings + { + Configuration = build.Configuration, + VersionSuffix = build.Version.Suffix, + IncludeSymbols = true, + OutputDirectory = "./artifacts/packages" + }; + foreach (var project in build.ProjectFiles) + { + //DotNetCorePack(project.FullPath, settings); + } +}); + +Task("Default") + .IsDependentOn("Build") + .IsDependentOn("Test") + .IsDependentOn("Pack") + .Does(() => +{ + util.PrintInfo(); +}); + +Task("Version") + .Does(() => +{ + Information($"{build.FullVersion()}"); +}); + +Task("Print") + .Does(() => +{ + util.PrintInfo(); +}); + +RunTarget(target); diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..7526d9f --- /dev/null +++ b/build.ps1 @@ -0,0 +1,183 @@ +<# + +.SYNOPSIS +This is a Powershell script to bootstrap a Cake build. + +.DESCRIPTION +This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) +and execute your Cake build script with the parameters you provide. + +.PARAMETER Script +The build script to execute. +.PARAMETER Target +The build script target to run. +.PARAMETER Configuration +The build configuration to use. +.PARAMETER Verbosity +Specifies the amount of information to be displayed. +.PARAMETER Experimental +Tells Cake to use the latest Roslyn release. +.PARAMETER WhatIf +Performs a dry run of the build script. +No tasks will be executed. +.PARAMETER Mono +Tells Cake to use the Mono scripting engine. +.PARAMETER SkipToolPackageRestore +Skips restoring of packages. +.PARAMETER ScriptArgs +Remaining arguments are added here. + +.LINK +http://cakebuild.net + +#> + +[CmdletBinding()] +Param( + [string]$Script = "build.cake", + [string]$Target = "Default", + [ValidateSet("Release", "Debug")] + [string]$Configuration = "Debug", + [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] + [string]$Verbosity = "Normal", + [switch]$Experimental = $true, + [Alias("DryRun","Noop")] + [switch]$WhatIf, + [switch]$Mono, + [switch]$SkipToolPackageRestore, + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$ScriptArgs +) + +[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null +function MD5HashFile([string] $filePath) +{ + if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) + { + return $null + } + + [System.IO.Stream] $file = $null; + [System.Security.Cryptography.MD5] $md5 = $null; + try + { + $md5 = [System.Security.Cryptography.MD5]::Create() + $file = [System.IO.File]::OpenRead($filePath) + return [System.BitConverter]::ToString($md5.ComputeHash($file)) + } + finally + { + if ($file -ne $null) + { + $file.Dispose() + } + } +} + +Write-Host "Preparing to run build script..." + +if(!$PSScriptRoot){ + $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent +} + +$TOOLS_DIR = Join-Path $PSScriptRoot "tools" +$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" +$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" +$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" +$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" +$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" + +# Should we use mono? +$UseMono = ""; +if($Mono.IsPresent) { + Write-Verbose -Message "Using the Mono based scripting engine." + $UseMono = "-mono" +} + +# Should we use the new Roslyn? +$UseExperimental = ""; +if($Experimental.IsPresent -and !($Mono.IsPresent)) { + Write-Verbose -Message "Using experimental version of Roslyn." + $UseExperimental = "-experimental" +} + +# Is this a dry run? +$UseDryRun = ""; +if($WhatIf.IsPresent) { + $UseDryRun = "-dryrun" +} + +# Make sure tools folder exists +if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { + Write-Verbose -Message "Creating tools directory..." + New-Item -Path $TOOLS_DIR -Type directory | out-null +} + +# Make sure that packages.config exist. +if (!(Test-Path $PACKAGES_CONFIG)) { + Write-Verbose -Message "Downloading packages.config..." + try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch { + Throw "Could not download packages.config." + } +} + +# Try find NuGet.exe in path if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Trying to find nuget.exe in PATH..." + $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) } + $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 + if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { + Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." + $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName + } +} + +# Try download NuGet.exe if not exists +if (!(Test-Path $NUGET_EXE)) { + Write-Verbose -Message "Downloading NuGet.exe..." + try { + (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE) + } catch { + Throw "Could not download NuGet.exe." + } +} + +# Save nuget.exe path to environment to be available to child processed +$ENV:NUGET_EXE = $NUGET_EXE + +# Restore tools from NuGet? +if(-Not $SkipToolPackageRestore.IsPresent) { + Push-Location + Set-Location $TOOLS_DIR + + # Check for changes in packages.config and remove installed tools if true. + [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) + if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or + ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { + Write-Verbose -Message "Missing or changed package.config hash..." + Remove-Item * -Recurse -Exclude packages.config,nuget.exe + } + + Write-Verbose -Message "Restoring tools from NuGet..." + $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" + + if ($LASTEXITCODE -ne 0) { + Throw "An error occured while restoring NuGet tools." + } + else + { + $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" + } + Write-Verbose -Message ($NuGetOutput | out-string) + Pop-Location +} + +# Make sure that Cake has been installed. +if (!(Test-Path $CAKE_EXE)) { + Throw "Could not find Cake.exe at $CAKE_EXE" +} + +# Start Cake +Write-Host "Running build script..." +Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs" +exit $LASTEXITCODE diff --git a/build/index.cake b/build/index.cake new file mode 100644 index 0000000..f0684bf --- /dev/null +++ b/build/index.cake @@ -0,0 +1,2 @@ +#load "./util.cake" +#load "./version.cake" diff --git a/build/util.cake b/build/util.cake new file mode 100644 index 0000000..db42eb7 --- /dev/null +++ b/build/util.cake @@ -0,0 +1,25 @@ +public class Util +{ + public Util(ICakeContext context, BuildParameters build) + { + Context = context; + Build = build; + } + + public ICakeContext Context { get; set; } + public BuildParameters Build { get; set; } + + public void PrintInfo() + { + Context.Information($@" +Version: {Build.FullVersion()} +Configuration: {Build.Configuration} +"); + } + + public static string CreateStamp() + { + var seconds = (long)(DateTime.UtcNow - new DateTime(2017, 1, 1)).TotalSeconds; + return seconds.ToString(); + } +} diff --git a/build/version.cake b/build/version.cake new file mode 100644 index 0000000..816dc6e --- /dev/null +++ b/build/version.cake @@ -0,0 +1,120 @@ +using System.Xml; + +public class BuildParameters +{ + public BuildParameters(ICakeContext context) + { + Context = context; + } + + public ICakeContext Context { get; } + public BuildVersion Version { get; private set; } + public string Configuration { get; private set; } + public bool IsTagged { get; private set; } + public bool IsCI { get; private set; } + public DirectoryPathCollection Projects { get; set; } + public DirectoryPathCollection TestProjects { get; set; } + public FilePathCollection ProjectFiles { get; set; } + public FilePathCollection TestProjectFiles { get; set; } + + public static BuildParameters Create(ICakeContext context) + { + var buildParameters = new BuildParameters(context); + buildParameters.Initialize(); + return buildParameters; + } + + public string FullVersion() + { + return Version.VersionWithSuffix(); + } + + private void Initialize() + { + InitializeCore(); + InitializeVersion(); + } + + private void InitializeCore() + { + Projects = Context.GetDirectories("./src/*"); + TestProjects = Context.GetDirectories("./test/*"); + ProjectFiles = Context.GetFiles("./src/*/*.csproj"); + TestProjectFiles = Context.GetFiles("./test/*/*.csproj"); + + var buildSystem = Context.BuildSystem(); + if (!buildSystem.IsLocalBuild) + { + IsCI = true; + if ((buildSystem.IsRunningOnAppVeyor && buildSystem.AppVeyor.Environment.Repository.Tag.IsTag) || + (buildSystem.IsRunningOnTravisCI && string.IsNullOrWhiteSpace(buildSystem.TravisCI.Environment.Build.Tag))) + { + IsTagged = true; + } + } + + Configuration = Context.Argument("Configuration", "Debug"); + if (IsCI) + { + Configuration = "Release"; + } + } + + private void InitializeVersion() + { + var versionFile = Context.File("./build/version.props"); + var content = System.IO.File.ReadAllText(versionFile.Path.FullPath); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(content); + + var versionMajor = doc.DocumentElement.SelectSingleNode("/Project/PropertyGroup/VersionMajor").InnerText; + var versionMinor = doc.DocumentElement.SelectSingleNode("/Project/PropertyGroup/VersionMinor").InnerText; + var versionPatch = doc.DocumentElement.SelectSingleNode("/Project/PropertyGroup/VersionPatch").InnerText; + var versionQuality = doc.DocumentElement.SelectSingleNode("/Project/PropertyGroup/VersionQuality").InnerText; + versionQuality = string.IsNullOrWhiteSpace(versionQuality) ? null : versionQuality; + + var suffix = versionQuality; + if (!IsTagged) + { + suffix += (IsCI ? "preview-" : "dev-") + Util.CreateStamp(); + } + suffix = string.IsNullOrWhiteSpace(suffix) ? null : suffix; + + Version = + new BuildVersion(int.Parse(versionMajor), int.Parse(versionMinor), int.Parse(versionPatch), versionQuality); + Version.Suffix = suffix; + } +} + +public class BuildVersion +{ + public BuildVersion(int major, int minor, int patch, string quality) + { + Major = major; + Minor = minor; + Patch = patch; + Quality = quality; + } + + public int Major { get; set; } + public int Minor { get; set; } + public int Patch { get; set; } + public string Quality { get; set; } + public string Suffix { get; set; } + + public string VersionWithoutQuality() + { + return $"{Major}.{Minor}.{Patch}"; + } + + public string Version() + { + return VersionWithoutQuality() + (Quality == null ? string.Empty : $"-{Quality}"); + } + + public string VersionWithSuffix() + { + return Version() + (Suffix == null ? string.Empty : $"-{Suffix}"); + } +} diff --git a/build/version.props b/build/version.props new file mode 100644 index 0000000..a5d60c8 --- /dev/null +++ b/build/version.props @@ -0,0 +1,9 @@ + + + 1 + 2 + 0 + + $(VersionMajor).$(VersionMinor).$(VersionPatch) + + diff --git a/src/NPOI.OOXML/NPOI.OOXML.csproj b/src/NPOI.OOXML/NPOI.OOXML.csproj index 2c8bf35..6ddea28 100644 --- a/src/NPOI.OOXML/NPOI.OOXML.csproj +++ b/src/NPOI.OOXML/NPOI.OOXML.csproj @@ -1,13 +1,14 @@  - - netstandard2.0;net461 - + + netstandard2.0;net461 + DotNetCore.NPOI + - - - - - + + + + + From f32697070a403e4fffdea35e4adc7ceb2088fb20 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Fri, 20 Jul 2018 23:34:21 +0800 Subject: [PATCH 11/38] update ci config file --- build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cake b/build.cake index 5255382..55bdb95 100644 --- a/build.cake +++ b/build.cake @@ -57,7 +57,7 @@ Task("Test") { foreach (var testProject in build.TestProjectFiles) { - DotNetCoreTest(testProject.FullPath); + //DotNetCoreTest(testProject.FullPath); } }); From 716ea821bd0e16822c8e79651db0d322ade9993d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=99=93=E4=B8=9C?= Date: Tue, 24 Jul 2018 20:40:40 +0800 Subject: [PATCH 12/38] add package id to csproj. --- src/NPOI.OOXML/NPOI.OOXML.csproj | 20 +++++++++---------- src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj | 1 + .../NPOI.OpenXmlFormats.csproj | 1 + src/NPOI/NPOI.csproj | 2 ++ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/NPOI.OOXML/NPOI.OOXML.csproj b/src/NPOI.OOXML/NPOI.OOXML.csproj index 6ddea28..804d0e8 100644 --- a/src/NPOI.OOXML/NPOI.OOXML.csproj +++ b/src/NPOI.OOXML/NPOI.OOXML.csproj @@ -1,14 +1,14 @@  - - netstandard2.0;net461 - DotNetCore.NPOI - - - - - - - + + netstandard2.0;net461 + DotNetCore.NPOI + + + + + + + diff --git a/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj b/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj index d4035aa..f42cf74 100644 --- a/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj +++ b/src/NPOI.OpenXml4Net/NPOI.OpenXml4Net.csproj @@ -2,6 +2,7 @@ netstandard2.0;net461 + DotNetCore.NPOI.OpenXml4Net diff --git a/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj b/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj index 509d34f..c301b92 100644 --- a/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj +++ b/src/NPOI.OpenXmlFormats/NPOI.OpenXmlFormats.csproj @@ -2,6 +2,7 @@ netstandard2.0;net461 + DotNetCore.NPOI.OpenXmlFormats diff --git a/src/NPOI/NPOI.csproj b/src/NPOI/NPOI.csproj index a5eeaaf..012fc1c 100644 --- a/src/NPOI/NPOI.csproj +++ b/src/NPOI/NPOI.csproj @@ -2,6 +2,8 @@ netstandard2.0;net461 + DotNetCore.NPOI.Core + false From b1f62041dd7edaf77acc42c9eb208f50f1f46cb0 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Wed, 25 Jul 2018 09:08:06 +0800 Subject: [PATCH 13/38] update build.cake --- build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cake b/build.cake index 55bdb95..f9df259 100644 --- a/build.cake +++ b/build.cake @@ -73,7 +73,7 @@ Task("Pack") }; foreach (var project in build.ProjectFiles) { - //DotNetCorePack(project.FullPath, settings); + DotNetCorePack(project.FullPath, settings); } }); From 0ef28a0d9768592f4ebe5673775e2cfbd67d3b66 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Wed, 25 Jul 2018 09:32:27 +0800 Subject: [PATCH 14/38] update package authors --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 542e807..0d888e9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ NPOI - .NET Core Community;Savorboard + dotnetcore;Savorboard https://github.com/dotnetcore/NPOI git $(MSBuildThisFileDirectory) From 538ef21f3ba658b8d78937353774727e81c49b1a Mon Sep 17 00:00:00 2001 From: Savorboard Date: Wed, 25 Jul 2018 09:50:58 +0800 Subject: [PATCH 15/38] update appveyor.yml --- appveyor.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index df615df..1d4c8fb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,4 +11,14 @@ skip_commits: - LICENSE build_script: - ps: ./build.ps1 -test: off \ No newline at end of file +test: off +artifacts: +- path: artifacts/packages/*.nupkg +deploy: + provider: NuGet + on: + appveyor_repo_tag: true + api_key: + secure: 62g+D0FPQQgVHQE+VaLPri7EAoQgu8WQbtXaawwa0c8o6fLxTc2oJSx2MgcLvpzN + skip_symbols: true + artifact: /artifacts\/packages\/.+\.nupkg/ \ No newline at end of file From 662a5c24b15e3cc53f4bb69a85aa5d5fc1814d11 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 26 Jul 2018 22:07:07 +0800 Subject: [PATCH 16/38] Update README.md --- README.md | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/README.md b/README.md index ae9621b..e690d25 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,7 @@ [![Build status](https://ci.appveyor.com/api/projects/status/k774la3yfxf0yfv8?svg=true)](https://ci.appveyor.com/project/yuleyule66/npoi) -This project is migrated from Tony Qu's [NPOI](https://github.com/tonyqus/npoi) by DotNETCore team. - -### NPOI of .net standard here, NPOI elsewhere - -This NPOI use .net standard 2.0 version. NPOI is still under at [https://github.com/tonyqus/npoi](https://github.com/tonyqus/npoi) +This project is migrated from Tony Qu's [NPOI](https://github.com/tonyqus/npoi) by .NET Core Community. ### NuGet Package @@ -15,15 +11,6 @@ This NPOI use .net standard 2.0 version. NPOI is still under at [https://github. Install-Package DotNetCore.NPOI ``` -### What is NPOI ? - -NPOI is the .NET version of POI Java project at http://poi.apache.org/. POI is an open source project which can help you read/write xls, doc, ppt files. It has a wide application. - -For example, you can use it to -* generate a Excel report without Microsoft Office suite installed on your server and more efficient than call Microsoft Excel ActiveX at background; -* extract text from Office documents to help you implement full-text indexing feature (most of time this feature is used to create search engines). -* extract images from Office documents -* generate Excel sheets that contains formulas ### How can it work on Linux? From ab3fc24f035fe8441da25f7e70a81086598e87c3 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Thu, 26 Jul 2018 22:20:57 +0800 Subject: [PATCH 17/38] Adjustment namepace System.Windows.Forms to NPOI. #56 --- src/NPOI/Label.cs | 7 ++----- src/NPOI/SS/Format/CellFormat.cs | 1 - src/NPOI/SS/Format/CellFormatPart.cs | 1 - src/NPOI/SS/Util/SheetUtil.cs | 1 - src/NPOI/TextRenderer.cs | 7 ++----- test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs | 1 - test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs | 4 +++- test/NPOI.TestCases/SS/Format/TestCellFormat.cs | 3 ++- 8 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/NPOI/Label.cs b/src/NPOI/Label.cs index 36f362e..bd7a796 100644 --- a/src/NPOI/Label.cs +++ b/src/NPOI/Label.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Drawing; +using System.Drawing; -namespace System.Windows.Forms +namespace NPOI { public class Label { diff --git a/src/NPOI/SS/Format/CellFormat.cs b/src/NPOI/SS/Format/CellFormat.cs index 73d7255..ca04a46 100644 --- a/src/NPOI/SS/Format/CellFormat.cs +++ b/src/NPOI/SS/Format/CellFormat.cs @@ -22,7 +22,6 @@ namespace NPOI.SS.Format using NPOI.SS.UserModel; using System.Text.RegularExpressions; using System.Collections.Generic; - using System.Windows.Forms; using System.Drawing; /** diff --git a/src/NPOI/SS/Format/CellFormatPart.cs b/src/NPOI/SS/Format/CellFormatPart.cs index d1bea03..0596aaf 100644 --- a/src/NPOI/SS/Format/CellFormatPart.cs +++ b/src/NPOI/SS/Format/CellFormatPart.cs @@ -24,7 +24,6 @@ namespace NPOI.SS.Format using System.Collections; using System.Text.RegularExpressions; using System.Text; - using System.Windows.Forms; /** * Objects of this class represent a single part of a cell format expression. diff --git a/src/NPOI/SS/Util/SheetUtil.cs b/src/NPOI/SS/Util/SheetUtil.cs index ef1bd67..1469e5f 100644 --- a/src/NPOI/SS/Util/SheetUtil.cs +++ b/src/NPOI/SS/Util/SheetUtil.cs @@ -21,7 +21,6 @@ namespace NPOI.SS.Util using NPOI.SS.UserModel; using System.Drawing; - using System.Windows.Forms; using System.Collections.Generic; /** diff --git a/src/NPOI/TextRenderer.cs b/src/NPOI/TextRenderer.cs index 7707075..513d454 100644 --- a/src/NPOI/TextRenderer.cs +++ b/src/NPOI/TextRenderer.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Text; +using System.Drawing; -namespace System.Windows.Forms +namespace NPOI { /// Provides methods used to measure and render text. This class cannot be inherited. public sealed class TextRenderer diff --git a/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs b/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs index 503b07c..7e88090 100644 --- a/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs +++ b/test/NPOI.TestCases/HSSF/UserModel/TestEscherGraphics.cs @@ -27,7 +27,6 @@ namespace TestCases.HSSF.UserModel using NUnit.Framework; - using System.Windows.Forms; /** * Tests the capabilities of the EscherGraphics class. diff --git a/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs b/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs index 6aea42d..369d9b2 100644 --- a/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs +++ b/test/NPOI.TestCases/SS/Format/CellFormatTestBase.cs @@ -14,6 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ + +using NPOI; + namespace TestCases.SS.Format { using System; @@ -21,7 +24,6 @@ namespace TestCases.SS.Format using System.Collections.Generic; using System.Drawing; using System.Text.RegularExpressions; - using System.Windows.Forms; using NUnit.Framework; using NPOI.HSSF.UserModel; using NPOI.SS.Format; diff --git a/test/NPOI.TestCases/SS/Format/TestCellFormat.cs b/test/NPOI.TestCases/SS/Format/TestCellFormat.cs index 93ae611..fec1ca5 100644 --- a/test/NPOI.TestCases/SS/Format/TestCellFormat.cs +++ b/test/NPOI.TestCases/SS/Format/TestCellFormat.cs @@ -15,13 +15,14 @@ limitations under the License. ==================================================================== */ +using NPOI; + namespace TestCases.SS.Format { using System; using System.Globalization; using System.Text; using System.Threading; - using System.Windows.Forms; using NPOI.HSSF.UserModel; using NPOI.SS.Format; From 62806d6a1dbeffc12e15fbb2cd7fb7fd01eb7a2b Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 30 Jul 2018 12:05:04 +0200 Subject: [PATCH 18/38] Add information about new dependencies since 1.2.0 --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e690d25..973a82a 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ Install-Package DotNetCore.NPOI ### How can it work on Linux? -On Linux, you need install `libgdiplus`. +On Linux, you need install `libgdiplus`. Since 1.2.0 libdl is also required. - Ubuntu 16.04 and above: - - apt-get install libgdiplus + - apt-get install libgdiplus libc6-dev - cd /usr/lib - ln -s libgdiplus.so gdiplus.dll - Fedora 23 and above: @@ -45,6 +45,12 @@ On Linux, you need install `libgdiplus`. RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories RUN apk --update add libgdiplus ``` + - Debian + ``` + FROM microsoft/dotnet:2.1-aspnetcore-runtime + RUN apt-get update && apt-get install -y libgdiplus libc6-dev && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll + ... + ``` ### Getting Started From 3828ac28062645c7f2224d499141ea43f107c13f Mon Sep 17 00:00:00 2001 From: Jon Ford Date: Fri, 14 Sep 2018 12:50:30 -0400 Subject: [PATCH 19/38] fix potential null reference exceptions, bump zip lib version, bump package version --- src/NPOI.OOXML/NPOI.OOXML.csproj | 3 ++- src/NPOI.OOXML/SS/Converter/ExcelToHtmlConverter.cs | 8 +++----- src/NPOI/NPOI.csproj | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/NPOI.OOXML/NPOI.OOXML.csproj b/src/NPOI.OOXML/NPOI.OOXML.csproj index 804d0e8..a22bced 100644 --- a/src/NPOI.OOXML/NPOI.OOXML.csproj +++ b/src/NPOI.OOXML/NPOI.OOXML.csproj @@ -2,7 +2,8 @@ netstandard2.0;net461 - DotNetCore.NPOI + DotNetCore.NPOI + 1.2.1 diff --git a/src/NPOI.OOXML/SS/Converter/ExcelToHtmlConverter.cs b/src/NPOI.OOXML/SS/Converter/ExcelToHtmlConverter.cs index 322e211..a346ecb 100644 --- a/src/NPOI.OOXML/SS/Converter/ExcelToHtmlConverter.cs +++ b/src/NPOI.OOXML/SS/Converter/ExcelToHtmlConverter.cs @@ -674,8 +674,6 @@ namespace NPOI.SS.Converter { style.Append("white-space: pre-wrap; "); ExcelToHtmlUtils.AppendAlign(style, cellStyle.Alignment); - StylesTable st = ((XSSFWorkbook)workbook).GetStylesSource(); - ThemesTable tt = st.GetTheme(); if (cellStyle.FillPattern == FillPattern.NoFill) { // no fill @@ -741,7 +739,7 @@ namespace NPOI.SS.Converter if (workbook is HSSFWorkbook) { - HSSFColor color = ((HSSFWorkbook)workbook).GetCustomPalette().GetColor(borderColor); + HSSFColor color = ((HSSFWorkbook)workbook).GetCustomPalette()?.GetColor(borderColor); if (color != null) { borderStyle.Append(' '); @@ -758,7 +756,7 @@ namespace NPOI.SS.Converter } else { - XSSFColor color = ((XSSFWorkbook)workbook).GetStylesSource().GetTheme().GetThemeColor(borderColor); + XSSFColor color = ((XSSFWorkbook)workbook)?.GetStylesSource()?.GetTheme()?.GetThemeColor(borderColor); if (color != null) { borderStyle.Append(' '); @@ -785,7 +783,7 @@ namespace NPOI.SS.Converter if (workbook is HSSFWorkbook) { - HSSFColor fontColor = ((HSSFWorkbook)workbook).GetCustomPalette().GetColor(font.Color); + HSSFColor fontColor = ((HSSFWorkbook)workbook).GetCustomPalette()?.GetColor(font.Color); if (fontColor != null) style.AppendFormat("color:{0}; " ,ExcelToHtmlUtils.GetColor(fontColor) ); } diff --git a/src/NPOI/NPOI.csproj b/src/NPOI/NPOI.csproj index 012fc1c..57f58ab 100644 --- a/src/NPOI/NPOI.csproj +++ b/src/NPOI/NPOI.csproj @@ -21,7 +21,7 @@ - + From 1c883236a7631ebe7cf4c38e818f00018a085c5d Mon Sep 17 00:00:00 2001 From: Savorboard Date: Sat, 15 Sep 2018 10:04:21 +0800 Subject: [PATCH 20/38] update version to 1.2.1 --- Directory.Build.props | 2 +- build/version.props | 2 +- src/NPOI.OOXML/NPOI.OOXML.csproj | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0d888e9..d4036ad 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ NPOI - dotnetcore;Savorboard + NCC;Savorboard https://github.com/dotnetcore/NPOI git $(MSBuildThisFileDirectory) diff --git a/build/version.props b/build/version.props index a5d60c8..ca676dc 100644 --- a/build/version.props +++ b/build/version.props @@ -2,7 +2,7 @@ 1 2 - 0 + 1 $(VersionMajor).$(VersionMinor).$(VersionPatch) diff --git a/src/NPOI.OOXML/NPOI.OOXML.csproj b/src/NPOI.OOXML/NPOI.OOXML.csproj index a22bced..a0c3a43 100644 --- a/src/NPOI.OOXML/NPOI.OOXML.csproj +++ b/src/NPOI.OOXML/NPOI.OOXML.csproj @@ -3,7 +3,6 @@ netstandard2.0;net461 DotNetCore.NPOI - 1.2.1 From 81778da1f4ff1866f91d526afe662cc7ee5b3f5c Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Thu, 11 Oct 2018 08:32:00 -0500 Subject: [PATCH 21/38] Fix column width calculations for AutoSizeColumn --- src/NPOI/SS/Util/SheetUtil.cs | 60 +++++++++++++++++------------------ src/NPOI/TextRenderer.cs | 26 --------------- 2 files changed, 30 insertions(+), 56 deletions(-) delete mode 100644 src/NPOI/TextRenderer.cs diff --git a/src/NPOI/SS/Util/SheetUtil.cs b/src/NPOI/SS/Util/SheetUtil.cs index 1469e5f..ac368bd 100644 --- a/src/NPOI/SS/Util/SheetUtil.cs +++ b/src/NPOI/SS/Util/SheetUtil.cs @@ -36,7 +36,7 @@ namespace NPOI.SS.Util // * but the docs say nothing about what particular character is used. // * '0' looks to be a good choice. // */ - private static char defaultChar = '0'; + private const char defaultChar = '0'; // /** // * This is the multiple that the font height is scaled by when determining the @@ -300,19 +300,18 @@ namespace NPOI.SS.Util ICellStyle style = cell.CellStyle; CellType cellType = cell.CellType; - IFont defaultFont = wb.GetFontAt((short)0); - Font windowsFont = IFont2Font(defaultFont); + // for formula cells we compute the cell width for the cached formula result if (cellType == CellType.Formula) cellType = cell.CachedFormulaResultType; IFont font = wb.GetFontAt(style.FontIndex); + Font windowsFont = IFont2Font(font); //AttributedString str; //TextLayout layout; double width = -1; - using (Bitmap bmp = new Bitmap(1, 1)) - using (Graphics g = Graphics.FromImage(bmp)) + using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) { if (cellType == CellType.String) { @@ -324,7 +323,6 @@ namespace NPOI.SS.Util //str = new AttributedString(txt); //copyAttributes(font, str, 0, txt.length()); - windowsFont = IFont2Font(font); if (rt.NumFormattingRuns > 0) { // TODO: support rich text fragments @@ -345,11 +343,11 @@ namespace NPOI.SS.Util // AffineTransform.getScaleInstance(1, fontHeightMultiple) // ); double angle = style.Rotation * 2.0 * Math.PI / 360.0; - SizeF sf = g.MeasureString(txt, windowsFont); + SizeF sf = MeasureString(g, txt, windowsFont); double x1 = Math.Abs(sf.Height * Math.Sin(angle)); double x2 = Math.Abs(sf.Width * Math.Cos(angle)); double w = Math.Round(x1 + x2, 0, MidpointRounding.ToEven); - width = Math.Max(width, (w / colspan / defaultCharWidth) * 2 + cell.CellStyle.Indention); + width = Math.Max(width, (w / colspan / defaultCharWidth) + cell.CellStyle.Indention); //width = Math.Max(width, // ((layout.getOutline(trans).getBounds().getWidth()/colspan)/defaultCharWidth) + // cell.getCellStyle().getIndention()); @@ -359,8 +357,8 @@ namespace NPOI.SS.Util //width = Math.Max(width, // ((layout.getBounds().getWidth()/colspan)/defaultCharWidth) + // cell.getCellStyle().getIndention()); - double w = Math.Round(g.MeasureString(txt, windowsFont).Width, 0, MidpointRounding.ToEven); - width = Math.Max(width, (w / colspan / defaultCharWidth) * 2 + cell.CellStyle.Indention); + double w = Math.Round(MeasureString(g, txt, windowsFont).Width, 0, MidpointRounding.ToEven); + width = Math.Max(width, (w / colspan / defaultCharWidth) + cell.CellStyle.Indention); } } } @@ -388,7 +386,6 @@ namespace NPOI.SS.Util String txt = sval + defaultChar; //str = new AttributedString(txt); //copyAttributes(font, str, 0, txt.length()); - windowsFont = IFont2Font(font); //layout = new TextLayout(str.getIterator(), fontRenderContext); if (style.Rotation != 0) { @@ -407,19 +404,19 @@ namespace NPOI.SS.Util // ((layout.getOutline(trans).getBounds().getWidth()/colspan)/defaultCharWidth) + // cell.getCellStyle().getIndention()); double angle = style.Rotation * 2.0 * Math.PI / 360.0; - SizeF sf = g.MeasureString(txt, windowsFont); + SizeF sf = MeasureString(g, txt, windowsFont); double x1 = sf.Height * Math.Sin(angle); double x2 = sf.Width * Math.Cos(angle); double w = Math.Round(x1 + x2, 0, MidpointRounding.ToEven); - width = Math.Max(width, (w / colspan / defaultCharWidth) * 2 + cell.CellStyle.Indention); + width = Math.Max(width, (w / colspan / defaultCharWidth) + cell.CellStyle.Indention); } else { //width = Math.max(width, // ((layout.getBounds().getWidth()/colspan)/defaultCharWidth) + // cell.getCellStyle().getIndention()); - double w = Math.Round(g.MeasureString(txt, windowsFont).Width, 0, MidpointRounding.ToEven); - width = Math.Max(width, (w * 1.0 / colspan / defaultCharWidth) * 2 + cell.CellStyle.Indention); + double w = Math.Round(MeasureString(g, txt, windowsFont).Width, 0, MidpointRounding.ToEven); + width = Math.Max(width, (w / colspan / defaultCharWidth) + cell.CellStyle.Indention); } } } @@ -449,14 +446,12 @@ namespace NPOI.SS.Util IWorkbook wb = sheet.Workbook; DataFormatter formatter = new DataFormatter(); - IFont defaultFont = wb.GetFontAt((short)0); //str = new AttributedString((defaultChar)); //copyAttributes(defaultFont, str, 0, 1); //layout = new TextLayout(str.Iterator, fontRenderContext); //int defaultCharWidth = (int)layout.Advance; - Font font = IFont2Font(defaultFont); - int defaultCharWidth = TextRenderer.MeasureText("" + new String(defaultChar, 1), font).Width; + int defaultCharWidth = getDefaultCharWidth(wb); //DummyEvaluator dummyEvaluator = new DummyEvaluator(); double width = -1; @@ -491,14 +486,11 @@ namespace NPOI.SS.Util IWorkbook wb = sheet.Workbook; DataFormatter formatter = new DataFormatter(); - IFont defaultFont = wb.GetFontAt((short)0); - //str = new AttributedString((defaultChar)); //copyAttributes(defaultFont, str, 0, 1); //layout = new TextLayout(str.Iterator, fontRenderContext); //int defaultCharWidth = (int)layout.Advance; - Font font = IFont2Font(defaultFont); - int defaultCharWidth = TextRenderer.MeasureText("" + new String(defaultChar, 1), font).Width; + int defaultCharWidth = getDefaultCharWidth(wb); double width = -1; for (int rowIdx = firstRow; rowIdx <= lastRow; ++rowIdx) @@ -662,15 +654,23 @@ namespace NPOI.SS.Util public static int getDefaultCharWidth(IWorkbook wb) { - //TODO: Implement! - return 1; - //throw new NotImplementedException(); - //IFont defaultFont = wb.GetFontAt(0); + IFont defaultFont = wb.GetFontAt(0); + Font font = IFont2Font(defaultFont); + using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) + { + double width = MeasureString(g, new string(defaultChar, 1), font).Width; + return (int)Math.Round(width, 0, MidpointRounding.ToEven); + } + } + + private static SizeF MeasureString(Graphics g, string text, Font font) + { + var size = g.MeasureString(text, font); - //IAttributedString str = new AttributedString(defaultChar.ToString()); - //copyAttributes(defaultFont, str, 0, 1); - //ITextLayout layout = new TextLayout(str.getIterator(), fontRenderContext); - //return (int)layout.getAdvance(); + // MeasureString adds padding so we do this to remove it + // https://stackoverflow.com/a/11708952/1409101 + var actualWidth = g.MeasureString(text + text, font).Width - size.Width; + return new SizeF(actualWidth, size.Height); } } } diff --git a/src/NPOI/TextRenderer.cs b/src/NPOI/TextRenderer.cs deleted file mode 100644 index 513d454..0000000 --- a/src/NPOI/TextRenderer.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Drawing; - -namespace NPOI -{ - /// Provides methods used to measure and render text. This class cannot be inherited. - public sealed class TextRenderer - { - private TextRenderer() - { - } - - /// Provides the size, in pixels, of the specified text when drawn with the specified font. - /// The text to measure. - /// The to apply to the measured text. - /// The , in pixels, of drawn on a single line with the specified . You can manipulate how the text is drawn by using one of the overloads that takes a parameter. For example, the default behavior of the is to add padding to the bounding rectangle of the drawn text to accommodate overhanging glyphs. If you need to draw a line of text without these extra spaces you should use the versions of and that take a and parameter. For an example, see . - public static Size MeasureText(string text, Font font) - { - if (string.IsNullOrEmpty(text)) - { - return Size.Empty; - } - Size result = new Size(19, 19); - return result; - } - } -} \ No newline at end of file From 45c15f887ee85c51a03eace0e2c01bb08dc6f129 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Thu, 11 Oct 2018 08:34:37 -0500 Subject: [PATCH 22/38] Fix General format of large numbers for AutoSizeColumn --- src/NPOI/SS/UserModel/DataFormatter.cs | 4 ++-- src/NPOI/SS/Util/Format.cs | 30 ++++++++++++++++---------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/NPOI/SS/UserModel/DataFormatter.cs b/src/NPOI/SS/UserModel/DataFormatter.cs index 379e903..97d7724 100644 --- a/src/NPOI/SS/UserModel/DataFormatter.cs +++ b/src/NPOI/SS/UserModel/DataFormatter.cs @@ -118,10 +118,10 @@ namespace NPOI.SS.UserModel invalidDateTimeString = buf.ToString(); } /** General FormatBase for whole numbers. */ - private static DecimalFormat generalWholeNumFormat = new DecimalFormat("0"); + private static DecimalFormat generalWholeNumFormat = new DecimalFormat("0", true); /** General FormatBase for decimal numbers. */ - private static DecimalFormat generalDecimalNumFormat = new DecimalFormat("#.##########"); + private static DecimalFormat generalDecimalNumFormat = new DecimalFormat("#.##########", true); /** A default FormatBase to use when a number pattern cannot be Parsed. */ private FormatBase defaultNumFormat; diff --git a/src/NPOI/SS/Util/Format.cs b/src/NPOI/SS/Util/Format.cs index 24c0445..21c7065 100644 --- a/src/NPOI/SS/Util/Format.cs +++ b/src/NPOI/SS/Util/Format.cs @@ -173,12 +173,20 @@ namespace NPOI.SS.Util private string pattern; + private bool isGeneral; + public DecimalFormat(string pattern) { if (pattern.IndexOf("'", StringComparison.Ordinal) != -1) throw new ArgumentException("invalid pattern"); this.pattern = pattern; } + + internal DecimalFormat(string pattern, bool isGeneral) : this(pattern) + { + this.isGeneral = isGeneral; + } + public string Pattern { get @@ -194,19 +202,19 @@ namespace NPOI.SS.Util } public override string Format(object obj, CultureInfo culture) { - //invalide fraction + // Invalid fraction pattern = RegexFraction.Replace(pattern, "/"); - + double n = Convert.ToDouble(obj, CultureInfo.InvariantCulture); + if (pattern.IndexOf("'", StringComparison.Ordinal) != -1) - { - //return ((double)obj).ToString(); - return Convert.ToDouble(obj, CultureInfo.InvariantCulture).ToString(culture); - } - else - { - return Convert.ToDouble(obj, CultureInfo.InvariantCulture).ToString(pattern, culture); - //return ((double)obj).ToString(pattern) ; - } + return n.ToString(culture); + + // Excel displays in scientific notation if the cell form is General and there are 12 or more digits + // https://support.office.com/en-us/article/display-numbers-in-scientific-exponential-notation-f85a96c0-18a1-4249-81c3-e934cd2aae25 + if (isGeneral && Math.Floor(Math.Log10(n) + 1) >= 12) + pattern = "E4"; + + return n.ToString(pattern, culture); } public override StringBuilder Format(object obj, StringBuilder toAppendTo, CultureInfo culture) From 09bd37ef91cce076502b9fa13ff7d42b5db80967 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Thu, 11 Oct 2018 15:50:09 -0500 Subject: [PATCH 23/38] Upgrade test projects and add netcoreapp2.0 target --- .gitignore | 4 + DotNetCore.NPOI.sln | 12 +- test/NPOI.OpenXml4Net/App.config | 22 - test/NPOI.OpenXml4Net/ConfigurationManager.cs | 26 + .../NPOI.OOXML4Net.Testcases.csproj | 143 +--- test/NPOI.OpenXml4Net/POIDataSamples.cs | 2 +- test/NPOI.OpenXml4Net/appsettings.json | 6 + test/NPOI.OpenXml4Net/packages.config | 4 - test/NPOI.OpenXmlFormats/App.config | 31 - .../NPOI.OOXML.TestCases.csproj | 254 +------ .../Properties/Settings.Designer.cs | 38 - .../Properties/Settings.settings | 9 - test/NPOI.OpenXmlFormats/appsettings.json | 6 + test/NPOI.OpenXmlFormats/packages.config | 5 - test/NPOI.TestCases/App.config | 29 - test/NPOI.TestCases/ConfigurationManager.cs | 26 + test/NPOI.TestCases/NPOI.TestCases.csproj | 680 ++---------------- .../NPOI.TestCases/Properties/AssemblyInfo.cs | 35 - .../Properties/Settings.Designer.cs | 38 - .../Properties/Settings.settings | 9 - .../NumberComparingSpreadsheetGenerator.cs | 5 +- .../NumberRenderingSpreadsheetGenerator.cs | 4 +- test/NPOI.TestCases/appsettings.json | 12 + test/NPOI.TestCases/packages.config | 4 - 24 files changed, 200 insertions(+), 1204 deletions(-) delete mode 100644 test/NPOI.OpenXml4Net/App.config create mode 100644 test/NPOI.OpenXml4Net/ConfigurationManager.cs create mode 100644 test/NPOI.OpenXml4Net/appsettings.json delete mode 100644 test/NPOI.OpenXml4Net/packages.config delete mode 100644 test/NPOI.OpenXmlFormats/Properties/Settings.Designer.cs delete mode 100644 test/NPOI.OpenXmlFormats/Properties/Settings.settings create mode 100644 test/NPOI.OpenXmlFormats/appsettings.json delete mode 100644 test/NPOI.OpenXmlFormats/packages.config delete mode 100644 test/NPOI.TestCases/App.config create mode 100644 test/NPOI.TestCases/ConfigurationManager.cs delete mode 100644 test/NPOI.TestCases/Properties/AssemblyInfo.cs delete mode 100644 test/NPOI.TestCases/Properties/Settings.Designer.cs delete mode 100644 test/NPOI.TestCases/Properties/Settings.settings create mode 100644 test/NPOI.TestCases/appsettings.json delete mode 100644 test/NPOI.TestCases/packages.config diff --git a/.gitignore b/.gitignore index 2613a46..474234a 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,9 @@ bld/ [Bb]in/ [Oo]bj/ +# KDiff3 +*.orig + # Visual Studio 2015 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot @@ -170,6 +173,7 @@ publish/ # NuGet v3's project.json files produces more ignoreable files *.nuget.props *.nuget.targets +tools/ # Microsoft Azure Build Output csx/ diff --git a/DotNetCore.NPOI.sln b/DotNetCore.NPOI.sln index d1a763f..30a03bb 100644 --- a/DotNetCore.NPOI.sln +++ b/DotNetCore.NPOI.sln @@ -84,8 +84,8 @@ Global {4D994508-5489-4342-9EE8-6FDDB0763E66}.Release|Any CPU.Build.0 = Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 2 Release|Any CPU.ActiveCfg = Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 2 Release|Any CPU.Build.0 = Release|Any CPU - {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 4 Release|Any CPU.ActiveCfg = .net 4 Release|Any CPU - {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 4 Release|Any CPU.Build.0 = .net 4 Release|Any CPU + {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 4 Release|Any CPU.ActiveCfg = Release|Any CPU + {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}..net 4 Release|Any CPU.Build.0 = Release|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.Debug|Any CPU.Build.0 = Debug|Any CPU {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9}.NPOI.Tools|Any CPU.ActiveCfg = Release|Any CPU @@ -98,14 +98,14 @@ Global {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}..net 4 Release|Any CPU.Build.0 = Release|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.NPOI.Tools|Any CPU.ActiveCfg = NPOI.Tools|Any CPU - {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.NPOI.Tools|Any CPU.Build.0 = NPOI.Tools|Any CPU + {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.NPOI.Tools|Any CPU.ActiveCfg = Debug|Any CPU + {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.NPOI.Tools|Any CPU.Build.0 = Debug|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0}.Release|Any CPU.Build.0 = Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 2 Release|Any CPU.ActiveCfg = Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 2 Release|Any CPU.Build.0 = Release|Any CPU - {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 4 Release|Any CPU.ActiveCfg = .net 4 Release|Any CPU - {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 4 Release|Any CPU.Build.0 = .net 4 Release|Any CPU + {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 4 Release|Any CPU.ActiveCfg = Release|Any CPU + {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}..net 4 Release|Any CPU.Build.0 = Release|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU {0BF8C464-8779-43CF-AD7A-B1109A86EAAE}.NPOI.Tools|Any CPU.ActiveCfg = Release|Any CPU diff --git a/test/NPOI.OpenXml4Net/App.config b/test/NPOI.OpenXml4Net/App.config deleted file mode 100644 index 34538d8..0000000 --- a/test/NPOI.OpenXml4Net/App.config +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/NPOI.OpenXml4Net/ConfigurationManager.cs b/test/NPOI.OpenXml4Net/ConfigurationManager.cs new file mode 100644 index 0000000..4a5e213 --- /dev/null +++ b/test/NPOI.OpenXml4Net/ConfigurationManager.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Configuration; +using System.Collections.Specialized; +using System.Linq; + +namespace System.Configuration +{ + // TODO: Replace this shim with actual Options class + public static class ConfigurationManager + { + public static NameValueCollection AppSettings { get; } + + static ConfigurationManager() + { + AppSettings = new ConfigurationBuilder() + .AddJsonFile("appsettings.json", false) + .Build() + .GetSection("AppSettings") + .GetChildren() + .Aggregate(new NameValueCollection(), (acc, cur) => + { + acc.Add(cur.Key, cur.Value); + return acc; + }); + } + } +} diff --git a/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj b/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj index 76349ec..46634da 100644 --- a/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj +++ b/test/NPOI.OpenXml4Net/NPOI.OOXML4Net.Testcases.csproj @@ -1,137 +1,28 @@ - - - + + - Debug - AnyCPU - 9.0.30729 - 2.0 - {F5A6FF78-2C51-44E8-9E31-CD1B3EF784E9} - Library - Properties + netcoreapp2.0;net461 OOXML4Net.Testcases OOXML4Net.Testcases - v4.6.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - + false - - true - full - false - ..\..\solution\Lib\.net4\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - false - false - - - pdbonly - true - ..\..\solution\Lib\.net4\ - TRACE - prompt - 4 - AllRules.ruleset - false - - - ..\..\solution\Lib\.net4\ - TRACE - true - pdbonly - AnyCPU - prompt - AllRules.ruleset - false - - - - ..\..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll - - - - - - - - - - - - - - - - - - - - - - + - - - Designer + + PreserveNewest + - + + + + + + - - {4d994508-5489-4342-9ee8-6fddb0763e66} - NPOI.OOXML - - - {b6aae93b-44b0-41a0-b478-0d72c115a40c} - NPOI.OpenXml4Net - - - {6452e3fd-ef04-4136-a04c-896b7c96d1cd} - NPOI.OpenXmlFormats - - - {2fb384cb-1041-47b5-9c0d-d6e9e5b4d4c0} - NPOI - + - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file + + diff --git a/test/NPOI.OpenXml4Net/POIDataSamples.cs b/test/NPOI.OpenXml4Net/POIDataSamples.cs index 5384b97..ed5e340 100644 --- a/test/NPOI.OpenXml4Net/POIDataSamples.cs +++ b/test/NPOI.OpenXml4Net/POIDataSamples.cs @@ -113,7 +113,7 @@ namespace TestCases private void Initialise() { - String dataDirName = System.Configuration.ConfigurationSettings.AppSettings[TEST_PROPERTY]; + String dataDirName = System.Configuration.ConfigurationManager.AppSettings[TEST_PROPERTY]; if (dataDirName == null) throw new Exception("Must set system property '" diff --git a/test/NPOI.OpenXml4Net/appsettings.json b/test/NPOI.OpenXml4Net/appsettings.json new file mode 100644 index 0000000..59eca89 --- /dev/null +++ b/test/NPOI.OpenXml4Net/appsettings.json @@ -0,0 +1,6 @@ +{ + "AppSettings": { + "POI.testdata.path": "..\\..\\..\\..\\test-data", + "ClientSettingsProvider.ServiceUri": "" + } +} \ No newline at end of file diff --git a/test/NPOI.OpenXml4Net/packages.config b/test/NPOI.OpenXml4Net/packages.config deleted file mode 100644 index ebeb58f..0000000 --- a/test/NPOI.OpenXml4Net/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/NPOI.OpenXmlFormats/App.config b/test/NPOI.OpenXmlFormats/App.config index 80bf945..b393ad0 100644 --- a/test/NPOI.OpenXmlFormats/App.config +++ b/test/NPOI.OpenXmlFormats/App.config @@ -1,40 +1,9 @@ - - -
- - - - - - - - - - ..\..\..\..\test-data - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/NPOI.OpenXmlFormats/NPOI.OOXML.TestCases.csproj b/test/NPOI.OpenXmlFormats/NPOI.OOXML.TestCases.csproj index 65f26de..8948b69 100644 --- a/test/NPOI.OpenXmlFormats/NPOI.OOXML.TestCases.csproj +++ b/test/NPOI.OpenXmlFormats/NPOI.OOXML.TestCases.csproj @@ -1,232 +1,46 @@ - - - + + - Debug - AnyCPU - 9.0.30729 - 2.0 - {0BF8C464-8779-43CF-AD7A-B1109A86EAAE} - Library - Properties + netcoreapp2.0;net461 NPOI.OOXML.Testcases NPOI.OOXML.Testcases - v4.6.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 3.5 - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - false - true - true - - - - - true - full - false - ..\..\solution\Lib\.net4\ - DEBUG;TRACE;HIDE_UNREACHABLE_CODE - prompt - 4 - AllRules.ruleset - false - false - - - pdbonly - true - ..\..\solution\Lib\.net4\ - TRACE;HIDE_UNREACHABLE_CODE - prompt - 4 - AllRules.ruleset - false - - - ..\..\solution\Lib\.net4\ - TRACE;HIDE_UNREACHABLE_CODE - true - pdbonly - AnyCPU - prompt - AllRules.ruleset - false + false + - - ..\..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll - - - - - - ..\..\packages\System.Drawing.Common.4.5.0\lib\net461\System.Drawing.Common.dll - - + + + + + + + + + + PreserveNewest + + - - True - True - Settings.settings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - Designer - - - - SettingsSingleFileGenerator - Settings.Designer.cs - + + + + - - {4d994508-5489-4342-9ee8-6fddb0763e66} - NPOI.OOXML - - - {b6aae93b-44b0-41a0-b478-0d72c115a40c} - NPOI.OpenXml4Net - - - {6452e3fd-ef04-4136-a04c-896b7c96d1cd} - NPOI.OpenXmlFormats - - - {2fb384cb-1041-47b5-9c0d-d6e9e5b4d4c0} - NPOI - - - {a920c2ba-8bfd-4f54-8401-7d1c0730f1f0} - NPOI.TestCases - + + - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file + + diff --git a/test/NPOI.OpenXmlFormats/Properties/Settings.Designer.cs b/test/NPOI.OpenXmlFormats/Properties/Settings.Designer.cs deleted file mode 100644 index 59db2ef..0000000 --- a/test/NPOI.OpenXmlFormats/Properties/Settings.Designer.cs +++ /dev/null @@ -1,38 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace NPOI.OOXML.Testcases.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("..\\..\\..\\test-data")] - public string TEST_PROPERTY { - get { - return ((string)(this["TEST_PROPERTY"])); - } - set { - this["TEST_PROPERTY"] = value; - } - } - } -} diff --git a/test/NPOI.OpenXmlFormats/Properties/Settings.settings b/test/NPOI.OpenXmlFormats/Properties/Settings.settings deleted file mode 100644 index 2e3cbab..0000000 --- a/test/NPOI.OpenXmlFormats/Properties/Settings.settings +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - ..\..\..\test-data - - - \ No newline at end of file diff --git a/test/NPOI.OpenXmlFormats/appsettings.json b/test/NPOI.OpenXmlFormats/appsettings.json new file mode 100644 index 0000000..59eca89 --- /dev/null +++ b/test/NPOI.OpenXmlFormats/appsettings.json @@ -0,0 +1,6 @@ +{ + "AppSettings": { + "POI.testdata.path": "..\\..\\..\\..\\test-data", + "ClientSettingsProvider.ServiceUri": "" + } +} \ No newline at end of file diff --git a/test/NPOI.OpenXmlFormats/packages.config b/test/NPOI.OpenXmlFormats/packages.config deleted file mode 100644 index 7749186..0000000 --- a/test/NPOI.OpenXmlFormats/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/test/NPOI.TestCases/App.config b/test/NPOI.TestCases/App.config deleted file mode 100644 index 48bc001..0000000 --- a/test/NPOI.TestCases/App.config +++ /dev/null @@ -1,29 +0,0 @@ - - - - -
- - - - - - - - - - - - - - - - - - ..\..\..\test-data - - - - diff --git a/test/NPOI.TestCases/ConfigurationManager.cs b/test/NPOI.TestCases/ConfigurationManager.cs new file mode 100644 index 0000000..4a5e213 --- /dev/null +++ b/test/NPOI.TestCases/ConfigurationManager.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Configuration; +using System.Collections.Specialized; +using System.Linq; + +namespace System.Configuration +{ + // TODO: Replace this shim with actual Options class + public static class ConfigurationManager + { + public static NameValueCollection AppSettings { get; } + + static ConfigurationManager() + { + AppSettings = new ConfigurationBuilder() + .AddJsonFile("appsettings.json", false) + .Build() + .GetSection("AppSettings") + .GetChildren() + .Aggregate(new NameValueCollection(), (acc, cur) => + { + acc.Add(cur.Key, cur.Value); + return acc; + }); + } + } +} diff --git a/test/NPOI.TestCases/NPOI.TestCases.csproj b/test/NPOI.TestCases/NPOI.TestCases.csproj index 90387e1..dc2a87e 100644 --- a/test/NPOI.TestCases/NPOI.TestCases.csproj +++ b/test/NPOI.TestCases/NPOI.TestCases.csproj @@ -1,630 +1,60 @@ - - - + + - Debug - AnyCPU - 9.0.30729 - 2.0 - {A920C2BA-8BFD-4F54-8401-7D1C0730F1F0} - Library - Properties + netcoreapp2.0;net461 TestCases - NPOI.TestCases - v4.6.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - false - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - false - true - - + false + $(DefineConstants);HIDE_UNREACHABLE_CODE - - true - full - false - ..\..\solution\Lib\.net4\ - DEBUG;TRACE;HIDE_UNREACHABLE_CODE - prompt - 4 - MinimumRecommendedRules.ruleset - false - - - pdbonly - true - ..\..\solution\Lib\.net4\ - TRACE;HIDE_UNREACHABLE_CODE - prompt - 4 - AllRules.ruleset - false - - - bin\NPOI.Tools\ - AllRules.ruleset - false - - - - ..\..\packages\NUnit.3.10.1\lib\net45\nunit.framework.dll - - - - - - ..\..\packages\System.Configuration.ConfigurationManager.4.4.0\lib\net461\System.Configuration.ConfigurationManager.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer + + + + + + + + + + + + + + + + + + PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {2fb384cb-1041-47b5-9c0d-d6e9e5b4d4c0} - NPOI - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/NPOI.TestCases/Properties/AssemblyInfo.cs b/test/NPOI.TestCases/Properties/AssemblyInfo.cs deleted file mode 100644 index 61e399c..0000000 --- a/test/NPOI.TestCases/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NPOI.TestCases")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("NPOI team")] -[assembly: AssemblyProduct("NPOI.TestCases")] -[assembly: AssemblyCopyright("Apache 2.0")] -[assembly: AssemblyTrademark("NPOI")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM componenets. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("d2a277c6-e48e-4e70-af22-2827e19b799a")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.5.0")] -[assembly: AssemblyFileVersion("1.2.5.0")] diff --git a/test/NPOI.TestCases/Properties/Settings.Designer.cs b/test/NPOI.TestCases/Properties/Settings.Designer.cs deleted file mode 100644 index 61bfeb7..0000000 --- a/test/NPOI.TestCases/Properties/Settings.Designer.cs +++ /dev/null @@ -1,38 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.261 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace TestCases.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("..\\..\\..\\test-data")] - public string TEST_PROPERTY { - get { - return ((string)(this["TEST_PROPERTY"])); - } - set { - this["TEST_PROPERTY"] = value; - } - } - } -} diff --git a/test/NPOI.TestCases/Properties/Settings.settings b/test/NPOI.TestCases/Properties/Settings.settings deleted file mode 100644 index 09eb0fa..0000000 --- a/test/NPOI.TestCases/Properties/Settings.settings +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - ..\..\..\test-data - - - \ No newline at end of file diff --git a/test/NPOI.TestCases/SS/Util/NumberComparingSpreadsheetGenerator.cs b/test/NPOI.TestCases/SS/Util/NumberComparingSpreadsheetGenerator.cs index c1ebb55..54c94c9 100644 --- a/test/NPOI.TestCases/SS/Util/NumberComparingSpreadsheetGenerator.cs +++ b/test/NPOI.TestCases/SS/Util/NumberComparingSpreadsheetGenerator.cs @@ -21,6 +21,8 @@ using System.Text; using NPOI.Util; using NPOI.HSSF.UserModel; using System.IO; +using NUnit.Framework; + namespace TestCases.SS.Util { @@ -132,7 +134,8 @@ namespace TestCases.SS.Util return sb.ToString(); } - public static void Main(String[] args) + //[Test] + public void Test() { IWorkbook wb = new HSSFWorkbook(); diff --git a/test/NPOI.TestCases/SS/Util/NumberRenderingSpreadsheetGenerator.cs b/test/NPOI.TestCases/SS/Util/NumberRenderingSpreadsheetGenerator.cs index 0e27484..ee2db31 100644 --- a/test/NPOI.TestCases/SS/Util/NumberRenderingSpreadsheetGenerator.cs +++ b/test/NPOI.TestCases/SS/Util/NumberRenderingSpreadsheetGenerator.cs @@ -22,6 +22,7 @@ using NPOI.Util; using NPOI.SS.UserModel; using System.Text; using System.IO; +using NUnit.Framework; namespace TestCases.SS.Util { @@ -140,7 +141,8 @@ namespace TestCases.SS.Util return sb.ToString(); } - public static void Main(String[] args) + //[Test] + public void Test() { WriteJavaDoc(); diff --git a/test/NPOI.TestCases/appsettings.json b/test/NPOI.TestCases/appsettings.json new file mode 100644 index 0000000..5057051 --- /dev/null +++ b/test/NPOI.TestCases/appsettings.json @@ -0,0 +1,12 @@ +{ + "AppSettings": { + "loggername": "test.Util.DummyPOILogger,NPOI.test", + "HSSF.testdata.path": "..\\..\\..\\..\\test-data\\hssf", + "POIFS.testdata.path": "..\\..\\..\\..\\test-data\\poifs", + "POI.testdata.path": "..\\..\\..\\..\\test-data", + "java.io.tmpdir": "..\\..\\..\\..\\test-data\\", + "poi.keep.tmp.files": "..\\..\\..\\..\\test-data\\", + "font.metrics.filename": "..\\..\\..\\..\\test-data\\font_metrics.properties", + "escher.data.path": "..\\..\\..\\..\\test-data\\ddf\\" + } +} \ No newline at end of file diff --git a/test/NPOI.TestCases/packages.config b/test/NPOI.TestCases/packages.config deleted file mode 100644 index ebeb58f..0000000 --- a/test/NPOI.TestCases/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From 8cd204d2f018a4965f1da2e788863d812e07b892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=99=93=E4=B8=9C?= Date: Fri, 12 Oct 2018 17:07:20 +0800 Subject: [PATCH 24/38] update version to 1.2.2. --- build/version.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.props b/build/version.props index ca676dc..205f53d 100644 --- a/build/version.props +++ b/build/version.props @@ -2,7 +2,7 @@ 1 2 - 1 + 2 $(VersionMajor).$(VersionMinor).$(VersionPatch) From f57a06ec7cd4d1faa828698e42f2c1bc5beca582 Mon Sep 17 00:00:00 2001 From: FroggieFrog Date: Fri, 8 Mar 2019 09:08:53 +0100 Subject: [PATCH 25/38] added badge for NuGet, fixed issues reported by markdownlint --- README.md | 59 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 973a82a..1270012 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,64 @@ -### NPOI +# NPOI +[![NuGet](https://img.shields.io/nuget/v/DotNetCore.NPOI.svg)](https://www.nuget.org/packages/DotNetCore.NPOI) [![Build status](https://ci.appveyor.com/api/projects/status/k774la3yfxf0yfv8?svg=true)](https://ci.appveyor.com/project/yuleyule66/npoi) This project is migrated from Tony Qu's [NPOI](https://github.com/tonyqus/npoi) by .NET Core Community. -### NuGet Package +## Install NuGet Package ```powershell - Install-Package DotNetCore.NPOI - ``` -### How can it work on Linux? +## How can it work on Linux? On Linux, you need install `libgdiplus`. Since 1.2.0 libdl is also required. - Ubuntu 16.04 and above: - - apt-get install libgdiplus libc6-dev - - cd /usr/lib - - ln -s libgdiplus.so gdiplus.dll + - apt-get install libgdiplus libc6-dev + - cd /usr/lib + - ln -s libgdiplus.so gdiplus.dll - Fedora 23 and above: - - dnf install libgdiplus - - cd /usr/lib64/ - - ln -s libgdiplus.so.0 gdiplus.dll + - dnf install libgdiplus + - cd /usr/lib64/ + - ln -s libgdiplus.so.0 gdiplus.dll - CentOS 7 and above: - - yum install autoconf automake libtool - - yum install freetype-devel fontconfig libXft-devel - - yum install libjpeg-turbo-devel libpng-devel giflib-devel libtiff-devel libexif-devel - - yum install glib2-devel cairo-devel - - git clone https://github.com/mono/libgdiplus - - cd libgdiplus - - ./autogen.sh - - make - - make install - - cd /usr/lib64/ - - ln -s /usr/local/lib/libgdiplus.so gdiplus.dll + - yum install autoconf automake libtool + - yum install freetype-devel fontconfig libXft-devel + - yum install libjpeg-turbo-devel libpng-devel giflib-devel libtiff-devel libexif-devel + - yum install glib2-devel cairo-devel + - git clone + - cd libgdiplus + - ./autogen.sh + - make + - make install + - cd /usr/lib64/ + - ln -s /usr/local/lib/libgdiplus.so gdiplus.dll - Docker - - Alpine + - Alpine + ``` # base sdk-alpine/aspnetcore-runtime-alpine images RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories RUN apk --update add libgdiplus ``` - - Debian + + - Debian + ``` FROM microsoft/dotnet:2.1-aspnetcore-runtime RUN apt-get update && apt-get install -y libgdiplus libc6-dev && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll ... ``` -### Getting Started +## Getting Started -#### Export Excel +### Export Excel ```csharp - var newFile = @"newbook.core.xlsx"; using (var fs = new FileStream(newFile, FileMode.Create, FileAccess.Write)) { @@ -93,10 +94,9 @@ using (var fs = new FileStream(newFile, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } - ``` -#### Export Word +### Export Word ```csharp var newFile2 = @"newbook.core.docx"; @@ -121,5 +121,4 @@ using (var fs = new FileStream(newFile2, FileMode.Create, FileAccess.Write)) { doc.Write(fs); } - ``` From a785f3082dd23501cfb8aa7ce7405c1f33df94a9 Mon Sep 17 00:00:00 2001 From: Dmytro Goldshteyn Date: Tue, 27 Aug 2019 12:49:54 +0200 Subject: [PATCH 26/38] Added possibility to create hyperlink run in paragraph --- .../XWPF/Usermodel/XWPFParagraph.cs | 20 +++++++++++++++++++ .../Wordprocessing/Paragraph.cs | 11 ++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/NPOI.OOXML/XWPF/Usermodel/XWPFParagraph.cs b/src/NPOI.OOXML/XWPF/Usermodel/XWPFParagraph.cs index 0990e05..ecb7d3b 100644 --- a/src/NPOI.OOXML/XWPF/Usermodel/XWPFParagraph.cs +++ b/src/NPOI.OOXML/XWPF/Usermodel/XWPFParagraph.cs @@ -1340,6 +1340,26 @@ namespace NPOI.XWPF.UserModel return xwpfRun; } + /** + * Appends a new hyperlink run to this paragraph + * + * @return a new hyperlink run + */ + public XWPFHyperlinkRun CreateHyperlinkRun(string rId) + { + CT_R r = new CT_R(); + r.AddNewRPr().rStyle = new CT_String() { val = "Hyperlink" }; + + CT_Hyperlink1 hl = paragraph.AddNewHyperlink(); + hl.history = ST_OnOff.on; + hl.id = rId; + hl.Items.Add(r); + XWPFHyperlinkRun xwpfRun = new XWPFHyperlinkRun(hl, r, this); + runs.Add(xwpfRun); + iRuns.Add(xwpfRun); + return xwpfRun; + } + /** * insert a new Run in RunArray * @param pos diff --git a/src/NPOI.OpenXmlFormats/Wordprocessing/Paragraph.cs b/src/NPOI.OpenXmlFormats/Wordprocessing/Paragraph.cs index 908ecfb..72ed657 100644 --- a/src/NPOI.OpenXmlFormats/Wordprocessing/Paragraph.cs +++ b/src/NPOI.OpenXmlFormats/Wordprocessing/Paragraph.cs @@ -371,6 +371,17 @@ namespace NPOI.OpenXmlFormats.Wordprocessing return r; } + public CT_Hyperlink1 AddNewHyperlink() + { + CT_Hyperlink1 hl = new CT_Hyperlink1(); + lock (this) + { + itemsField.Add(hl); + itemsElementNameField.Add(ParagraphItemsChoiceType.hyperlink); + } + return hl; + } + [XmlElement("ItemsElementName", Order = 2)] [XmlIgnore] public List ItemsElementName From f58dcbe78f14575f11628917c62a61ba17f1b448 Mon Sep 17 00:00:00 2001 From: Morten Date: Fri, 30 Aug 2019 13:04:37 +0200 Subject: [PATCH 27/38] Styles.xml: fix default patternType when attribute is missing --- src/NPOI.OpenXmlFormats/Spreadsheet/Styles/CT_PatternFill.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NPOI.OpenXmlFormats/Spreadsheet/Styles/CT_PatternFill.cs b/src/NPOI.OpenXmlFormats/Spreadsheet/Styles/CT_PatternFill.cs index d199cff..487c9c7 100644 --- a/src/NPOI.OpenXmlFormats/Spreadsheet/Styles/CT_PatternFill.cs +++ b/src/NPOI.OpenXmlFormats/Spreadsheet/Styles/CT_PatternFill.cs @@ -50,7 +50,9 @@ namespace NPOI.OpenXmlFormats.Spreadsheet if (node == null) return null; CT_PatternFill ctObj = new CT_PatternFill(); - if (node.Attributes["patternType"] != null) + if (node.Attributes["patternType"] == null) + ctObj.patternType = ST_PatternType.solid; + else ctObj.patternType = (ST_PatternType)Enum.Parse(typeof(ST_PatternType), node.Attributes["patternType"].Value); foreach (XmlNode childNode in node.ChildNodes) { From fc5326114bc2ed813df7014713412f534026fe4d Mon Sep 17 00:00:00 2001 From: Dmytro Goldshteyn Date: Mon, 2 Sep 2019 12:10:56 +0200 Subject: [PATCH 28/38] update AbstractNumId by adding --- src/NPOI.OOXML/XWPF/Usermodel/XWPFNumbering.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/NPOI.OOXML/XWPF/Usermodel/XWPFNumbering.cs b/src/NPOI.OOXML/XWPF/Usermodel/XWPFNumbering.cs index 1deee85..9b05491 100644 --- a/src/NPOI.OOXML/XWPF/Usermodel/XWPFNumbering.cs +++ b/src/NPOI.OOXML/XWPF/Usermodel/XWPFNumbering.cs @@ -249,6 +249,7 @@ namespace NPOI.XWPF.UserModel int pos = abstractNums.Count; if (abstractNum.GetAbstractNum() != null) { // Use the current CTAbstractNum if it exists + abstractNum.GetAbstractNum().abstractNumId = pos.ToString(); ctNumbering.AddNewAbstractNum().Set(abstractNum.GetAbstractNum()); } else From 762b48b329d98f21650e39eb289e12eabbb102b4 Mon Sep 17 00:00:00 2001 From: Savorboard Date: Mon, 7 Oct 2019 09:37:39 +0800 Subject: [PATCH 29/38] upgrade nuget package ShartZipLib to version 1.2.0 --- src/NPOI/NPOI.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NPOI/NPOI.csproj b/src/NPOI/NPOI.csproj index 57f58ab..4262b2a 100644 --- a/src/NPOI/NPOI.csproj +++ b/src/NPOI/NPOI.csproj @@ -21,7 +21,7 @@ - + From 8279e855621c771e99933cc42e9b4d9ea36e93f6 Mon Sep 17 00:00:00 2001 From: Harrison Saturley-Hall Date: Fri, 10 Apr 2020 11:40:07 -0400 Subject: [PATCH 30/38] Fix typo of IndexedColor "LemonChiffon" name mapping dictionary --- src/NPOI.OOXML/SS/UserModel/IndexedColors.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs b/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs index ea08bdf..9301a8e 100644 --- a/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs +++ b/src/NPOI.OOXML/SS/UserModel/IndexedColors.cs @@ -168,7 +168,7 @@ namespace NPOI.SS.UserModel mappingName.Add("grey50percent", IndexedColors.Grey50Percent); mappingName.Add("cornflowerblue", IndexedColors.CornflowerBlue); mappingName.Add("maroon", IndexedColors.Maroon); - mappingName.Add("lemonchilffon", IndexedColors.LemonChiffon); + mappingName.Add("lemonchiffon", IndexedColors.LemonChiffon); mappingName.Add("orchid", IndexedColors.Orchid); mappingName.Add("coral", IndexedColors.Coral); mappingName.Add("royalblue", IndexedColors.RoyalBlue); From 789eaa4280cac3d9cdca336c9188978ebadd3974 Mon Sep 17 00:00:00 2001 From: alexinea Date: Tue, 13 Oct 2020 23:20:12 +0800 Subject: [PATCH 31/38] Added simplified Chinese readme file. --- README.md | 7 ++- README.zh_cn.md | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 README.zh_cn.md diff --git a/README.md b/README.md index 1270012..dfaa66b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# NPOI +

+ English | + 中文 +

+ +# NPOI [![NuGet](https://img.shields.io/nuget/v/DotNetCore.NPOI.svg)](https://www.nuget.org/packages/DotNetCore.NPOI) [![Build status](https://ci.appveyor.com/api/projects/status/k774la3yfxf0yfv8?svg=true)](https://ci.appveyor.com/project/yuleyule66/npoi) diff --git a/README.zh_cn.md b/README.zh_cn.md new file mode 100644 index 0000000..b9525b3 --- /dev/null +++ b/README.zh_cn.md @@ -0,0 +1,129 @@ +

+ English | + 中文 +

+ +# NPOI + +[![NuGet](https://img.shields.io/nuget/v/DotNetCore.NPOI.svg)](https://www.nuget.org/packages/DotNetCore.NPOI) +[![Build status](https://ci.appveyor.com/api/projects/status/k774la3yfxf0yfv8?svg=true)](https://ci.appveyor.com/project/yuleyule66/npoi) + +本项目由 .NET Core Community 迁移自上游项目 Tony Qu 的 [NPOI](https://github.com/tonyqus/npoi) 。 + +## 安装 NuGet 包 + +```powershell +Install-Package DotNetCore.NPOI +``` + +## 如何在 Linux 上使用? + +在 Linux 上,你需要安装 `libgdiplus`。从 1.2.0 开始,还需要 libdl。 + +- Ubuntu 16.04 及以上: + - apt-get install libgdiplus libc6-dev + - cd /usr/lib + - ln -s libgdiplus.so gdiplus.dll +- Fedora 23 及以上: + - dnf install libgdiplus + - cd /usr/lib64/ + - ln -s libgdiplus.so.0 gdiplus.dll +- CentOS 7 及以上: + - yum install autoconf automake libtool + - yum install freetype-devel fontconfig libXft-devel + - yum install libjpeg-turbo-devel libpng-devel giflib-devel libtiff-devel libexif-devel + - yum install glib2-devel cairo-devel + - git clone + - cd libgdiplus + - ./autogen.sh + - make + - make install + - cd /usr/lib64/ + - ln -s /usr/local/lib/libgdiplus.so gdiplus.dll + +- Docker + - Alpine + + ``` + # base sdk-alpine/aspnetcore-runtime-alpine images + + RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories + RUN apk --update add libgdiplus + ``` + + - Debian + + ``` + FROM microsoft/dotnet:2.1-aspnetcore-runtime + RUN apt-get update && apt-get install -y libgdiplus libc6-dev && ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll + ... + ``` + +## 开始 + +### 导出 Excel + +```csharp +var newFile = @"newbook.core.xlsx"; + +using (var fs = new FileStream(newFile, FileMode.Create, FileAccess.Write)) { + + IWorkbook workbook = new XSSFWorkbook(); + + ISheet sheet1 = workbook.CreateSheet("Sheet1"); + + sheet1.AddMergedRegion(new CellRangeAddress(0, 0, 0, 10)); + var rowIndex = 0; + IRow row = sheet1.CreateRow(rowIndex); + row.Height = 30 * 80; + row.CreateCell(0).SetCellValue("this is content"); + sheet1.AutoSizeColumn(0); + rowIndex++; + + var sheet2 = workbook.CreateSheet("Sheet2"); + var style1 = workbook.CreateCellStyle(); + style1.FillForegroundColor = HSSFColor.Blue.Index2; + style1.FillPattern = FillPattern.SolidForeground; + + var style2 = workbook.CreateCellStyle(); + style2.FillForegroundColor = HSSFColor.Yellow.Index2; + style2.FillPattern = FillPattern.SolidForeground; + + var cell2 = sheet2.CreateRow(0).CreateCell(0); + cell2.CellStyle = style1; + cell2.SetCellValue(0); + + cell2 = sheet2.CreateRow(1).CreateCell(0); + cell2.CellStyle = style2; + cell2.SetCellValue(1); + + workbook.Write(fs); +} +``` + +### 导出 Word + +```csharp +var newFile2 = @"newbook.core.docx"; +using (var fs = new FileStream(newFile2, FileMode.Create, FileAccess.Write)) { + XWPFDocument doc = new XWPFDocument(); + var p0 = doc.CreateParagraph(); + p0.Alignment = ParagraphAlignment.CENTER; + XWPFRun r0 = p0.CreateRun(); + r0.FontFamily = "microsoft yahei"; + r0.FontSize = 18; + r0.IsBold = true; + r0.SetText("This is title"); + + var p1 = doc.CreateParagraph(); + p1.Alignment = ParagraphAlignment.LEFT; + p1.IndentationFirstLine = 500; + XWPFRun r1 = p1.CreateRun(); + r1.FontFamily = "·ÂËÎ"; + r1.FontSize = 12; + r1.IsBold = true; + r1.SetText("This is content, content content content content content content content content content"); + + doc.Write(fs); +} +``` From 845e42bbaa373e0bc63faf34b68c27ec99744960 Mon Sep 17 00:00:00 2001 From: alexinea Date: Tue, 13 Oct 2020 23:22:00 +0800 Subject: [PATCH 32/38] Rename readme.zh-CN.md 's file name. --- README.zh_cn.md => README.zh-CN.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README.zh_cn.md => README.zh-CN.md (100%) diff --git a/README.zh_cn.md b/README.zh-CN.md similarity index 100% rename from README.zh_cn.md rename to README.zh-CN.md From c2e233573a01424f8523154267b75fa413010324 Mon Sep 17 00:00:00 2001 From: alexinea Date: Tue, 13 Oct 2020 23:29:09 +0800 Subject: [PATCH 33/38] Update readme and add Announcement section. --- README.md | 4 ++++ README.zh-CN.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/README.md b/README.md index dfaa66b..631bbc7 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ This project is migrated from Tony Qu's [NPOI](https://github.com/tonyqus/npoi) by .NET Core Community. +## Announcement + +The root upstream project of the NPOI project is [tonyqus/NPOI](https://github.com/tonyqus/NPOI), which is the .NET version of the [Apache POI](https://github.com/apache/poi). [tonyqus/NPOI](https://github.com/tonyqus/NPOI) is the project with the largest number of downloads of [nuget package](https://www.nuget.org/packages/NPOI/) in the Chinese-speaking area. Developers at home and abroad know that this kind of glory and contribution cannot be obliterated. Just like Linux has derived so many distributions, but no one can deny Linus's contribution. + ## Install NuGet Package ```powershell diff --git a/README.zh-CN.md b/README.zh-CN.md index b9525b3..511a000 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -10,6 +10,10 @@ 本项目由 .NET Core Community 迁移自上游项目 Tony Qu 的 [NPOI](https://github.com/tonyqus/npoi) 。 +## 通告 + +NPOI 项目的最上游项目是 [tonyqus/NPOI](https://github.com/tonyqus/NPOI),该项目是 [Apache POI](https://github.com/apache/poi) 项目的 .NET 版本。[tonyqus/NPOI](https://github.com/tonyqus/NPOI) 是华语地区 [NUGET](https://www.nuget.org/packages/NPOI/) 包下载量最大的项目,为全体海内外开发者们所知,这种荣耀与贡献是谁也不可能抹杀的,就像 Linux 衍生出那么多版本,但又有谁会否认 Linus Torvalds 的贡献? + ## 安装 NuGet 包 ```powershell From 27b1523b14382ffaf194877f0f3435ee87cd98d7 Mon Sep 17 00:00:00 2001 From: Lewis Zou Date: Tue, 13 Oct 2020 23:34:08 +0800 Subject: [PATCH 34/38] Update README.zh-CN.md --- README.zh-CN.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.zh-CN.md b/README.zh-CN.md index 511a000..b826229 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -14,6 +14,20 @@ NPOI 项目的最上游项目是 [tonyqus/NPOI](https://github.com/tonyqus/NPOI),该项目是 [Apache POI](https://github.com/apache/poi) 项目的 .NET 版本。[tonyqus/NPOI](https://github.com/tonyqus/NPOI) 是华语地区 [NUGET](https://www.nuget.org/packages/NPOI/) 包下载量最大的项目,为全体海内外开发者们所知,这种荣耀与贡献是谁也不可能抹杀的,就像 Linux 衍生出那么多版本,但又有谁会否认 Linus Torvalds 的贡献? +dotnetcore/NPOI 作为 tonyqus/NPOI 项目的下游项目,在 2016 年至 2017 年社区急需 .NET Core 版本的 NPOI,且**明确**收到 tony qu 无意迁移和维护 .NET Core 版本的情况下诞生,它是 tonyqus/NPOI 的迁移版本。tony qu 亦多次通过 @alexinea 询问 dotnetcore/NPOI 单元测试的进度。dotnetcore/NPOI 的迁移方式是杨晓东老师(我们对他的尊称,而不是他自称)一个文件一个文件地迁移的,两个项目的命名空间和文件目录都有不少变化。在第一次上传的自述文件(README.MD)中,杨晓东老师说明了此项目是 NPOI 的 Core 版本,NPOI 项目依然在 tonyqus/NPOI 下。 + +``` +This project is for NPOI Core. NPOI is still under at [https://github.com/tonyqus/npoi](https://github.com/tonyqus/npoi) +``` + +杨晓东老师无意维护 NFX 版本,而 tony qu 亦无意做 .NET Core 版本的迁移和维护,因此说明这只是 NPOI 的 Core 版本,原版本还是在 tonyqus/NPOI 并无不妥。在后续的版本中,杨晓东老师在自述文件中也明确了这个版本是迁移自 tonyqus/NPOI。因 **明确** 得知 tony qu 无意迁移和维护 .NET Core 版本,在 GitHub 的协助下,移除了 dotnetcore/NPOI 对 tonyqus/NPOI 的 fork 关系,作为独立下游项目单独存在与发展,如同 Linux 下游分发项目。做开源的,每个人、每个时间段、每个场景都不可能做到那么完善和严谨,只要没有违反开源协议即无过错。杨晓东老师无意、NCC 无意抹杀 tony qu 的任何功劳。 + +我们认为,dotnetcore/NPOI 完成了她的历史使命,在社区最需要 .NET Core 版本 NPOI 的时候给出了一份选择。作为上游项目,tony qu 本无权力要求下游项目归档,可有人听过上游 Linux 可以要求下游的 Linux 归档的?他在发给 @alexinea 和杨晓东老师的邮件中指出 NCC「没有必要靠 NPOI 来撑台面」。经 NCC 内部讨论一致决定:不与其争论,并屏蔽了他。于是暴风雨来了,tony qu 联系劝说 NCC 成员项目离开 NCC 、联系微软要 DMCA dotnetcore(因为他觉得 github.com/dotnetcore 太正式)等,进而导致了一系列 QQ、微信群里的争论。但 NCC QQ 大群和微信群,反而没怎么讨论此事——因为大家都很明白,dotnetcore/NPOI 并未违反任何开源协议。 + +对于某些人在微信群、QQ 群截取图片传递给 tony qu 的做法,我们实在不敢恭维。Natasha 作者一开始就说过**要争论他可以直接拉群让 tonyqu 来讨论**,不知道传话人可有把这句话带到给 tony qu 呢?更何况 Natasha 群也不是 NCC 的群,它只是 Natasha 技术学习群,却被 tony qu 认定为 NCC 的群,群内的发言也被 tony qu 到处散播,不知道是不知道还是真的不知道。 + +我们无意花更多的时间与 tony qu 纠缠,经 NCC PMC 讨论,现决定将 dotnetcore/NPOI 存档,以避免 NCC 社区陷入更大的纠纷。如无意外,今后我们也不会再针对这件事做出任何回应。我们感谢海内外开发者们的支持和理解,愿与包括各位在内的广大开发者和开源社区一道,为 .NET 技术和生态做出更多贡献。 + ## 安装 NuGet 包 ```powershell From 17d1d10f5f3e11b95d825340015d58300caa1074 Mon Sep 17 00:00:00 2001 From: Lewis Zou Date: Tue, 13 Oct 2020 23:37:09 +0800 Subject: [PATCH 35/38] Update README.md --- README.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 631bbc7..8e9298f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,39 @@ This project is migrated from Tony Qu's [NPOI](https://github.com/tonyqus/npoi) ## Announcement -The root upstream project of the NPOI project is [tonyqus/NPOI](https://github.com/tonyqus/NPOI), which is the .NET version of the [Apache POI](https://github.com/apache/poi). [tonyqus/NPOI](https://github.com/tonyqus/NPOI) is the project with the largest number of downloads of [nuget package](https://www.nuget.org/packages/NPOI/) in the Chinese-speaking area. Developers at home and abroad know that this kind of glory and contribution cannot be obliterated. Just like Linux has derived so many distributions, but no one can deny Linus's contribution. +The root upstream project of the NPOI project is tonyqus/NPOI, which is the .NET version of the Apache POI project. tonyqus/NPOI is the project with the largest number of downloads of nuget packages in the Chinese-speaking area. Developers at home and abroad know that this kind of glory and contribution cannot be obliterated. Just like Linux has derived so many distributions, but no one can deny Linus's contribution. + +dotnetcore/NPOI, as a downstream project of the tonyqus/NPOI project, was born at the end of 2016. At that time, developers urgently needed the .NET Core version of NPOI. At that time, after receiving a reply from tonyqus, he **made it clear** that he "has no intention of migrating and maintaining the .NET Core version." So dotnetcore/NPOI was born. It forks from tonyqus/NPOI and is known to upstream project authors. The upstream project author has repeatedly asked @alexinea about the progress of the dotnetcore/NPOI unit test. + +The migration method of dotnetcore/NPOI is that @yang-xiaodong migrates file by file. All readers can understand that the namespace and file directory between the two projects have undergone a lot of changes. In the readme file (README.MD) uploaded for the first time, @yang-xiaodong has stated that this project is the .NET Core version of NPOI, and the NPOI project is still under tonyqus/NPOI. + +``` +This project is for NPOI Core. NPOI is still under at [https://github.com/tonyqus/npoi](https://github.com/tonyqus/npoi) +``` + +Mr. Yang has no intention of maintaining the .NET Framework version, and tony qu has no intention of migrating and maintaining the .NET Core version. Therefore, it means that this project is only the .NET Core version of NPOI, and the original version is still in tonyqus. + +In subsequent versions, Mr. Yang also made it clear in the readme file that this project was migrated from tonyqus/NPOI. + +After @yang-xiaodong learned that @tonyqus clearly did not intend to migrate and maintain tonyqus/NPOI to .NET Core, with the assistance of GitHub, removed the fork relationship between dotnetcore/NPOI and tonyqus/NPOI. Since then, the dotnetcore/NPOI project has become an independent downstream project to exist and develop independently, just like a Linux downstream distribution project. + +For open source projects, it is impossible for everyone to be so perfect and rigorous at all times, as long as they do not violate the open source agreement or license. Mr. Yang has no intention and NCC has no intention to obliterate any glory of @tonyqus. + +We believe that dotnetcore/NPOI has completed her historical mission. She gave a choice when the community most needed the .NET Core version of NPOI. + +As an upstream project, tony qu has no right to require downstream projects to be archived. Has anyone heard that upstream Linux distributions can require downstream Linux distributions to be archived? + +After discussion within the NCC PMC, it was decided not to argue with him, and to block him at the organizational level. + +So the storm came, tony qu contacted to persuade NCC member projects to leave NCC, contacted Microsoft to ask for DMCA dotnetcore (because he thought github.com/dotnetcore was too formal) and so on. This series of actions led to controversy in the Natasha WeChat group. But on the contrary, the NCC QQ group and WeChat group did not discuss this matter-because everyone knew that dotnetcore/NPOI did not violate any open source license. + +We condemn the behavior of some people passing screenshots of chats in the Natasha WeChat group to tony qu. The author of Natasha, LanX, said at the beginning: If everyone wants to argue, he can just create a new group and let tonyqu come in and discuss it together. I wonder if the person who secretly took the screenshot told tony qu this sentence? + +What's more, the Natasha WeChat group is not an NCC group. It is only a Natasha technology studying group, but it is recognized as an NCC group by tony qu. The speeches in the group are also spread everywhere by tony qu. I don't know if he really doesn't know the difference, or pretends he doesn't know the difference. + +We don't intend to spend more time entangled with tony qu. After discussing with the NCC PMC, we now decide to archive dotnetcore/NPOI to prevent the NCC community from getting into bigger disputes. If there is no accident, we will not make any response to this matter in the future. + +We NCC thank the developers for their support and understanding, and we NCC are willing to work with developers and open source communities, including you, to make more contributions to .NET technology and ecology. ## Install NuGet Package From b8fccd26133974c73f687b522f01130afa428555 Mon Sep 17 00:00:00 2001 From: alexinea Date: Tue, 13 Oct 2020 23:45:57 +0800 Subject: [PATCH 36/38] Update README --- README.md | 20 +++++++++++--------- README.zh-CN.md | 12 +++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8e9298f..c97f24e 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ This project is migrated from Tony Qu's [NPOI](https://github.com/tonyqus/npoi) ## Announcement -The root upstream project of the NPOI project is tonyqus/NPOI, which is the .NET version of the Apache POI project. tonyqus/NPOI is the project with the largest number of downloads of nuget packages in the Chinese-speaking area. Developers at home and abroad know that this kind of glory and contribution cannot be obliterated. Just like Linux has derived so many distributions, but no one can deny Linus's contribution. +The root upstream project of the NPOI project is [tonyqus/NPOI](https://github.com/tonyqus/NPOI), which is the .NET version of the [Apache POI](https://github.com/apache/poi). [tonyqus/NPOI](https://github.com/tonyqus/NPOI) is the project with the largest number of downloads of nuget packages in the Chinese-speaking area. Developers at home and abroad know that this kind of glory and contribution cannot be obliterated. Just like Linux has derived so many distributions, but no one can deny Linus's contribution. -dotnetcore/NPOI, as a downstream project of the tonyqus/NPOI project, was born at the end of 2016. At that time, developers urgently needed the .NET Core version of NPOI. At that time, after receiving a reply from tonyqus, he **made it clear** that he "has no intention of migrating and maintaining the .NET Core version." So dotnetcore/NPOI was born. It forks from tonyqus/NPOI and is known to upstream project authors. The upstream project author has repeatedly asked @alexinea about the progress of the dotnetcore/NPOI unit test. +[dotnetcore/NPOI](https://github.com/dotnetcore/NPOI), as a downstream project of the [tonyqus/NPOI](https://github.com/tonyqus/NPOI) project, was born at the end of 2016. At that time, developers urgently needed the .NET Core version of NPOI. At that time, after receiving a reply from tonyqus, he **made it clear** that he "has no intention of migrating and maintaining the .NET Core version." So [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) was born. It forks from [tonyqus/NPOI](https://github.com/tonyqus/NPOI) and is known to upstream project authors. The upstream project author has repeatedly asked @alexinea about the progress of the [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) unit test. -The migration method of dotnetcore/NPOI is that @yang-xiaodong migrates file by file. All readers can understand that the namespace and file directory between the two projects have undergone a lot of changes. In the readme file (README.MD) uploaded for the first time, @yang-xiaodong has stated that this project is the .NET Core version of NPOI, and the NPOI project is still under tonyqus/NPOI. +The migration method of [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) is that @yang-xiaodong migrates file by file. All readers can understand that the namespace and file directory between the two projects have undergone a lot of changes. In the readme file (README.MD) uploaded for the first time, @yang-xiaodong has stated that this project is the .NET Core version of NPOI, and the NPOI project is still under [tonyqus/NPOI](https://github.com/tonyqus/NPOI). ``` This project is for NPOI Core. NPOI is still under at [https://github.com/tonyqus/npoi](https://github.com/tonyqus/npoi) @@ -24,27 +24,29 @@ This project is for NPOI Core. NPOI is still under at [https://github.com/tonyqu Mr. Yang has no intention of maintaining the .NET Framework version, and tony qu has no intention of migrating and maintaining the .NET Core version. Therefore, it means that this project is only the .NET Core version of NPOI, and the original version is still in tonyqus. -In subsequent versions, Mr. Yang also made it clear in the readme file that this project was migrated from tonyqus/NPOI. +In subsequent versions, Mr. Yang also made it clear in the readme file that this project was migrated from [tonyqus/NPOI](https://github.com/tonyqus/NPOI). -After @yang-xiaodong learned that @tonyqus clearly did not intend to migrate and maintain tonyqus/NPOI to .NET Core, with the assistance of GitHub, removed the fork relationship between dotnetcore/NPOI and tonyqus/NPOI. Since then, the dotnetcore/NPOI project has become an independent downstream project to exist and develop independently, just like a Linux downstream distribution project. +After @yang-xiaodong learned that @tonyqus clearly did not intend to migrate and maintain [tonyqus/NPOI](https://github.com/tonyqus/NPOI) to .NET Core, with the assistance of GitHub, removed the fork relationship between [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) and [tonyqus/NPOI](https://github.com/tonyqus/NPOI). Since then, the [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) project has become an independent downstream project to exist and develop independently, just like a Linux downstream distribution project. For open source projects, it is impossible for everyone to be so perfect and rigorous at all times, as long as they do not violate the open source agreement or license. Mr. Yang has no intention and NCC has no intention to obliterate any glory of @tonyqus. -We believe that dotnetcore/NPOI has completed her historical mission. She gave a choice when the community most needed the .NET Core version of NPOI. +We believe that [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) has completed her historical mission. She gave a choice when the community most needed the .NET Core version of NPOI. As an upstream project, tony qu has no right to require downstream projects to be archived. Has anyone heard that upstream Linux distributions can require downstream Linux distributions to be archived? After discussion within the NCC PMC, it was decided not to argue with him, and to block him at the organizational level. -So the storm came, tony qu contacted to persuade NCC member projects to leave NCC, contacted Microsoft to ask for DMCA dotnetcore (because he thought github.com/dotnetcore was too formal) and so on. This series of actions led to controversy in the Natasha WeChat group. But on the contrary, the NCC QQ group and WeChat group did not discuss this matter-because everyone knew that dotnetcore/NPOI did not violate any open source license. +So the storm came, tony qu contacted to persuade NCC member projects to leave NCC, contacted Microsoft to ask for DMCA dotnetcore (because he thought github.com/dotnetcore was too formal) and so on. This series of actions led to controversy in the Natasha WeChat group. But on the contrary, the NCC QQ group and WeChat group did not discuss this matter-because everyone knew that [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) did not violate any open source license. We condemn the behavior of some people passing screenshots of chats in the Natasha WeChat group to tony qu. The author of Natasha, LanX, said at the beginning: If everyone wants to argue, he can just create a new group and let tonyqu come in and discuss it together. I wonder if the person who secretly took the screenshot told tony qu this sentence? What's more, the Natasha WeChat group is not an NCC group. It is only a Natasha technology studying group, but it is recognized as an NCC group by tony qu. The speeches in the group are also spread everywhere by tony qu. I don't know if he really doesn't know the difference, or pretends he doesn't know the difference. -We don't intend to spend more time entangled with tony qu. After discussing with the NCC PMC, we now decide to archive dotnetcore/NPOI to prevent the NCC community from getting into bigger disputes. If there is no accident, we will not make any response to this matter in the future. +We don't intend to spend more time entangled with tony qu. After discussing with the NCC PMC, we now decide to archive [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) to prevent the NCC community from getting into bigger disputes. If there is no accident, we will not make any response to this matter in the future. -We NCC thank the developers for their support and understanding, and we NCC are willing to work with developers and open source communities, including you, to make more contributions to .NET technology and ecology. +[We NCC](https://github.com/dotnetcore) thank the developers for their support and understanding, and we NCC are willing to work with developers and open source communities, including you, to make more contributions to .NET technology and ecology. + +--- ## Install NuGet Package diff --git a/README.zh-CN.md b/README.zh-CN.md index b826229..6f215e2 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -14,19 +14,21 @@ NPOI 项目的最上游项目是 [tonyqus/NPOI](https://github.com/tonyqus/NPOI),该项目是 [Apache POI](https://github.com/apache/poi) 项目的 .NET 版本。[tonyqus/NPOI](https://github.com/tonyqus/NPOI) 是华语地区 [NUGET](https://www.nuget.org/packages/NPOI/) 包下载量最大的项目,为全体海内外开发者们所知,这种荣耀与贡献是谁也不可能抹杀的,就像 Linux 衍生出那么多版本,但又有谁会否认 Linus Torvalds 的贡献? -dotnetcore/NPOI 作为 tonyqus/NPOI 项目的下游项目,在 2016 年至 2017 年社区急需 .NET Core 版本的 NPOI,且**明确**收到 tony qu 无意迁移和维护 .NET Core 版本的情况下诞生,它是 tonyqus/NPOI 的迁移版本。tony qu 亦多次通过 @alexinea 询问 dotnetcore/NPOI 单元测试的进度。dotnetcore/NPOI 的迁移方式是杨晓东老师(我们对他的尊称,而不是他自称)一个文件一个文件地迁移的,两个项目的命名空间和文件目录都有不少变化。在第一次上传的自述文件(README.MD)中,杨晓东老师说明了此项目是 NPOI 的 Core 版本,NPOI 项目依然在 tonyqus/NPOI 下。 +[dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) 作为 [tonyqus/NPOI](https://github.com/tonyqus/NPOI) 项目的下游项目,在 2016 年至 2017 年社区急需 .NET Core 版本的 NPOI,且**明确**收到 tony qu 无意迁移和维护 .NET Core 版本的情况下诞生,它是 [tonyqus/NPOI](https://github.com/tonyqus/NPOI) 的迁移版本。tony qu 亦多次通过 @alexinea 询问 [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) 单元测试的进度。[dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) 的迁移方式是杨晓东老师(我们对他的尊称,而不是他自称)一个文件一个文件地迁移的,两个项目的命名空间和文件目录都有不少变化。在第一次上传的自述文件(README.MD)中,杨晓东老师说明了此项目是 NPOI 的 Core 版本,NPOI 项目依然在 [tonyqus/NPOI](https://github.com/tonyqus/NPOI) 下。 ``` This project is for NPOI Core. NPOI is still under at [https://github.com/tonyqus/npoi](https://github.com/tonyqus/npoi) ``` -杨晓东老师无意维护 NFX 版本,而 tony qu 亦无意做 .NET Core 版本的迁移和维护,因此说明这只是 NPOI 的 Core 版本,原版本还是在 tonyqus/NPOI 并无不妥。在后续的版本中,杨晓东老师在自述文件中也明确了这个版本是迁移自 tonyqus/NPOI。因 **明确** 得知 tony qu 无意迁移和维护 .NET Core 版本,在 GitHub 的协助下,移除了 dotnetcore/NPOI 对 tonyqus/NPOI 的 fork 关系,作为独立下游项目单独存在与发展,如同 Linux 下游分发项目。做开源的,每个人、每个时间段、每个场景都不可能做到那么完善和严谨,只要没有违反开源协议即无过错。杨晓东老师无意、NCC 无意抹杀 tony qu 的任何功劳。 +杨晓东老师无意维护 NFX 版本,而 tony qu 亦无意做 .NET Core 版本的迁移和维护,因此说明这只是 NPOI 的 Core 版本,原版本还是在 [tonyqus/NPOI](https://github.com/tonyqus/NPOI) 并无不妥。在后续的版本中,杨晓东老师在自述文件中也明确了这个版本是迁移自 [tonyqus/NPOI](https://github.com/tonyqus/NPOI)。因 **明确** 得知 tony qu 无意迁移和维护 .NET Core 版本,在 GitHub 的协助下,移除了 [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) 对 [tonyqus/NPOI](https://github.com/tonyqus/NPOI) 的 fork 关系,作为独立下游项目单独存在与发展,如同 Linux 下游分发项目。做开源的,每个人、每个时间段、每个场景都不可能做到那么完善和严谨,只要没有违反开源协议即无过错。杨晓东老师无意、NCC 无意抹杀 tony qu 的任何功劳。 -我们认为,dotnetcore/NPOI 完成了她的历史使命,在社区最需要 .NET Core 版本 NPOI 的时候给出了一份选择。作为上游项目,tony qu 本无权力要求下游项目归档,可有人听过上游 Linux 可以要求下游的 Linux 归档的?他在发给 @alexinea 和杨晓东老师的邮件中指出 NCC「没有必要靠 NPOI 来撑台面」。经 NCC 内部讨论一致决定:不与其争论,并屏蔽了他。于是暴风雨来了,tony qu 联系劝说 NCC 成员项目离开 NCC 、联系微软要 DMCA dotnetcore(因为他觉得 github.com/dotnetcore 太正式)等,进而导致了一系列 QQ、微信群里的争论。但 NCC QQ 大群和微信群,反而没怎么讨论此事——因为大家都很明白,dotnetcore/NPOI 并未违反任何开源协议。 +我们认为,[dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) 完成了她的历史使命,在社区最需要 .NET Core 版本 NPOI 的时候给出了一份选择。作为上游项目,tony qu 本无权力要求下游项目归档,可有人听过上游 Linux 可以要求下游的 Linux 归档的?他在发给 @alexinea 和杨晓东老师的邮件中指出 NCC「没有必要靠 NPOI 来撑台面」。经 NCC 内部讨论一致决定:不与其争论,并屏蔽了他。于是暴风雨来了,tony qu 联系劝说 NCC 成员项目离开 NCC 、联系微软要 DMCA dotnetcore(因为他觉得 github.com/dotnetcore 太正式)等,进而导致了一系列 QQ、微信群里的争论。但 NCC QQ 大群和微信群,反而没怎么讨论此事——因为大家都很明白,[dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) 并未违反任何开源协议。 -对于某些人在微信群、QQ 群截取图片传递给 tony qu 的做法,我们实在不敢恭维。Natasha 作者一开始就说过**要争论他可以直接拉群让 tonyqu 来讨论**,不知道传话人可有把这句话带到给 tony qu 呢?更何况 Natasha 群也不是 NCC 的群,它只是 Natasha 技术学习群,却被 tony qu 认定为 NCC 的群,群内的发言也被 tony qu 到处散播,不知道是不知道还是真的不知道。 +对于某些人在微信群、QQ 群截取图片传递给 tony qu 的做法,我们实在不敢恭维。Natasha 作者一开始就说过**要争论他可以直接拉群让 tony qu 来讨论**,不知道传话人可有把这句话带到给 tony qu 呢?更何况 Natasha 群也不是 NCC 的群,它只是 Natasha 技术学习群,却被 tony qu 认定为 NCC 的群,群内的发言也被 tony qu 到处散播,不知道是不知道还是真的不知道。 -我们无意花更多的时间与 tony qu 纠缠,经 NCC PMC 讨论,现决定将 dotnetcore/NPOI 存档,以避免 NCC 社区陷入更大的纠纷。如无意外,今后我们也不会再针对这件事做出任何回应。我们感谢海内外开发者们的支持和理解,愿与包括各位在内的广大开发者和开源社区一道,为 .NET 技术和生态做出更多贡献。 +我们无意花更多的时间与 tony qu 纠缠,经 NCC PMC 讨论,现决定将 [dotnetcore/NPOI](https://github.com/dotnetcore/NPOI) 存档,以避免 NCC 社区陷入更大的纠纷。如无意外,今后我们也不会再针对这件事做出任何回应。我们感谢海内外开发者们的支持和理解,愿与包括各位在内的广大开发者和开源社区一道,为 .NET 技术和生态做出更多贡献。 + +--- ## 安装 NuGet 包 From 391875603e4fde0de467cfa8443262e5ad106ceb Mon Sep 17 00:00:00 2001 From: alexinea Date: Wed, 14 Oct 2020 11:55:50 +0800 Subject: [PATCH 37/38] UPDATE README We believe that the loss of the "What is NPOI" section is not a work error. Due to the authorization of the upstream project author, removing this information does not violate the agreement or license. Because the upstream project has fully explained the relationship between NPOI and Apache POI. Here we will add it back. --- README.md | 10 ++++++++++ README.zh-CN.md | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/README.md b/README.md index c97f24e..4da0524 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,16 @@ We don't intend to spend more time entangled with tony qu. After discussing with --- +## What is NPOI ? + +NPOI is the .NET version of POI Java project at http://poi.apache.org/. POI is an open source project which can help you read/write xls, doc, ppt files. It has a wide application. + +For example, you can use it to +* generate a Excel report without Microsoft Office suite installed on your server and more efficient than call Microsoft Excel ActiveX at background; +* extract text from Office documents to help you implement full-text indexing feature (most of time this feature is used to create search engines). +* extract images from Office documents +* generate Excel sheets that contains formulas + ## Install NuGet Package ```powershell diff --git a/README.zh-CN.md b/README.zh-CN.md index 6f215e2..b458523 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -30,6 +30,15 @@ This project is for NPOI Core. NPOI is still under at [https://github.com/tonyqu --- +## 什么是 NPOI? + +NPOI 是 [Apache POI](https://github.com/poi) 项目的 .NET 版本。POI 是一个开源项目,能帮助你读/写 xls、doc、ppt 等文件。它具有广泛用途,如: + +* 在服务器未安装 Microsoft Office 套件的情况下生成 Excel 报告,并且比在后台调用 Microsoft Excel ActiveX 效率更高; +* 从 Office 文档中提取文本,以帮助你实现全文索引功能(大多数情况下,此功能用于创建搜索引擎); +* 从 Office 文档中提取图像; +* 生成包含公式的 Excel 工作表。 + ## 安装 NuGet 包 ```powershell From 0deab0b7c9f4525121b5ca6d36cdc13789becb07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=99=93=E4=B8=9C?= Date: Tue, 24 Nov 2020 13:06:06 +0800 Subject: [PATCH 38/38] According to the request of nuget.org, add license and project statement. --- NOTICE.TXT | 181 +++++++++++++++++++++++++++++++ build/version.props | 2 +- src/NPOI.OOXML/NPOI.OOXML.csproj | 31 ++++-- 3 files changed, 201 insertions(+), 13 deletions(-) create mode 100644 NOTICE.TXT diff --git a/NOTICE.TXT b/NOTICE.TXT new file mode 100644 index 0000000..eb262a7 --- /dev/null +++ b/NOTICE.TXT @@ -0,0 +1,181 @@ +dotnetcore/NPOI is a downstream project of the tonyqus/NPOI project, which is licensed under the Apache 2.0 license and available at: https://github.com/nissl-lab/npoi + +---------------------------------------------- + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "{}" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. \ No newline at end of file diff --git a/build/version.props b/build/version.props index 205f53d..ceee721 100644 --- a/build/version.props +++ b/build/version.props @@ -2,7 +2,7 @@ 1 2 - 2 + 3 $(VersionMajor).$(VersionMinor).$(VersionPatch) diff --git a/src/NPOI.OOXML/NPOI.OOXML.csproj b/src/NPOI.OOXML/NPOI.OOXML.csproj index a0c3a43..cc791c7 100644 --- a/src/NPOI.OOXML/NPOI.OOXML.csproj +++ b/src/NPOI.OOXML/NPOI.OOXML.csproj @@ -1,14 +1,21 @@  - - netstandard2.0;net461 - DotNetCore.NPOI - - - - - - - - - + + netstandard2.0;net461 + DotNetCore.NPOI + + + + + + + + + + + true + true + + + + \ No newline at end of file