示例#1
0
    private static async ValueTask WriteAsync(
        Stream stream,
        SpreadsheetBuffer buffer,
        List <Style> styles,
        CancellationToken token)
    {
        buffer.Advance(Utf8Helper.GetBytes(Header, buffer.GetSpan()));

        var fontLookup = await WriteFontsAsync(stream, buffer, styles, token).ConfigureAwait(false);

        var fillLookup = await WriteFillsAsync(stream, buffer, styles, token).ConfigureAwait(false);

        await buffer.WriteAsciiStringAsync(XmlPart1, stream, token).ConfigureAwait(false);

        var styleCount = styles.Count + 1;

        if (styleCount.GetNumberOfDigits() > buffer.FreeCapacity)
        {
            await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
        }

        var sb = new StringBuilder();

        sb.Append(styleCount);

        // The default style must be the first one (index 0)
        sb.Append("\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\"/>");
        await buffer.WriteAsciiStringAsync(sb.ToString(), stream, token).ConfigureAwait(false);

        sb.Clear();

        for (var i = 0; i < styles.Count; ++i)
        {
            var style     = styles[i];
            var fontIndex = fontLookup[style.Font];
            var fillIndex = fillLookup[style.Fill];

            sb.Clear();
            sb.Append("<xf numFmtId=\"0\"");
            sb.Append(" fontId=\"").Append(fontIndex).Append('"');
            if (fontIndex > 0)
            {
                sb.Append(" applyFont=\"1\"");
            }

            sb.Append(" fillId=\"").Append(fillIndex).Append('"');
            if (fillIndex > 1)
            {
                sb.Append(" applyFill=\"1\"");
            }

            sb.Append(" xfId=\"0\"/>");
            await buffer.WriteAsciiStringAsync(sb.ToString(), stream, token).ConfigureAwait(false);
        }

        await buffer.WriteAsciiStringAsync(XmlPart2, stream, token).ConfigureAwait(false);

        await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
    }
示例#2
0
 public Worksheet(Stream stream, SpreadsheetBuffer buffer)
 {
     _stream           = stream;
     _buffer           = buffer;
     _cellWriter       = new CellWriter(buffer);
     _dataCellWriter   = new DataCellWriter(buffer);
     _styledCellWriter = new StyledCellWriter(buffer);
     _nextRowIndex     = 1;
 }
示例#3
0
    private bool GetBytes(StyleId styleId, SpreadsheetBuffer buffer)
    {
        var bytes        = buffer.GetSpan();
        var bytesWritten = SpanHelper.GetBytes(StyledCellHelper.BeginStyledBooleanCell, bytes);

        bytesWritten += Utf8Helper.GetBytes(styleId.Id, bytes.Slice(bytesWritten));
        bytesWritten += SpanHelper.GetBytes(EndStyleValueBytes(), bytes.Slice(bytesWritten));
        buffer.Advance(bytesWritten);
        return(true);
    }
    private static bool GetBytes(StyleId styleId, SpreadsheetBuffer buffer)
    {
        var bytes        = buffer.GetSpan();
        var bytesWritten = SpanHelper.GetBytes(StyledCellHelper.BeginStyledNumberCell, bytes);

        bytesWritten += Utf8Helper.GetBytes(styleId.Id, bytes.Slice(bytesWritten));
        bytesWritten += SpanHelper.GetBytes(StyledCellHelper.EndStyleNullValue, bytes.Slice(bytesWritten));
        buffer.Advance(bytesWritten);
        return(true);
    }
示例#5
0
    private static async ValueTask <Dictionary <Fill, int> > WriteFillsAsync(
        Stream stream,
        SpreadsheetBuffer buffer,
        List <Style> styles,
        CancellationToken token)
    {
        var       defaultFill  = new Fill();
        const int defaultCount = 2;

        var uniqueFills = new Dictionary <Fill, int> {
            { defaultFill, 0 }
        };

        for (var i = 0; i < styles.Count; ++i)
        {
            var fill = styles[i].Fill;
            uniqueFills[fill] = 0;
        }

        var sb         = new StringBuilder();
        var totalCount = uniqueFills.Count + defaultCount - 1;

        sb.Append("<fills count=\"").Append(totalCount).Append("\">");

        // The 2 default fills must come first
        sb.Append("<fill><patternFill patternType=\"none\"/></fill>");
        sb.Append("<fill><patternFill patternType=\"gray125\"/></fill>");
        await buffer.WriteAsciiStringAsync(sb.ToString(), stream, token).ConfigureAwait(false);

        var fillIndex = defaultCount;

        foreach (var fill in uniqueFills.Keys.ToArray())
        {
            if (fill.Equals(defaultFill))
            {
                continue;
            }

            sb.Clear();
            sb.AppendFill(fill);
            await buffer.WriteAsciiStringAsync(sb.ToString(), stream, token).ConfigureAwait(false);

            uniqueFills[fill] = fillIndex;
            ++fillIndex;
        }

        await buffer.WriteAsciiStringAsync("</fills>", stream, token).ConfigureAwait(false);

        return(uniqueFills);
    }
示例#6
0
    private static async ValueTask <Dictionary <Font, int> > WriteFontsAsync(
        Stream stream,
        SpreadsheetBuffer buffer,
        List <Style> styles,
        CancellationToken token)
    {
        var       defaultFont  = new Font();
        const int defaultCount = 1;

        var uniqueFonts = new Dictionary <Font, int> {
            { defaultFont, 0 }
        };

        for (var i = 0; i < styles.Count; ++i)
        {
            var font = styles[i].Font;
            uniqueFonts[font] = 0;
        }

        var sb         = new StringBuilder();
        var totalCount = uniqueFonts.Count + defaultCount - 1;

        sb.Append("<fonts count=\"").Append(totalCount).Append("\">");

        // The default font must be the first one (index 0)
        sb.Append("<font><sz val=\"11\"/><name val=\"Calibri\"/></font>");
        await buffer.WriteAsciiStringAsync(sb.ToString(), stream, token).ConfigureAwait(false);

        var fontIndex = defaultCount;

        foreach (var font in uniqueFonts.Keys.ToArray())
        {
            if (font.Equals(defaultFont))
            {
                continue;
            }

            sb.Clear();
            sb.AppendFont(font);
            await buffer.WriteAsciiStringAsync(sb.ToString(), stream, token).ConfigureAwait(false);

            uniqueFonts[font] = fontIndex;
            ++fontIndex;
        }

        await buffer.WriteAsciiStringAsync("</fonts>", stream, token).ConfigureAwait(false);

        return(uniqueFonts);
    }
    public static async ValueTask WriteAsync(
        ZipArchive archive,
        CompressionLevel compressionLevel,
        SpreadsheetBuffer buffer,
        List <string> worksheetPaths,
        bool hasStylesXml,
        CancellationToken token)
    {
        var stream = archive.CreateEntry("xl/_rels/workbook.xml.rels", compressionLevel).Open();

#if NETSTANDARD2_0
        using (stream)
#else
        await using (stream.ConfigureAwait(false))
#endif
        {
            buffer.Advance(Utf8Helper.GetBytes(Header, buffer.GetSpan()));

            for (var i = 0; i < worksheetPaths.Count; ++i)
            {
                var path               = worksheetPaths[i];
                var sheetId            = i + 1;
                var sheetElementLength = GetSheetElementByteCount(path, sheetId);

                if (sheetElementLength > buffer.FreeCapacity)
                {
                    await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
                }

                buffer.Advance(GetSheetElementBytes(path, sheetId, buffer.GetSpan()));
            }

            var bufferNeeded = Footer.Length + (hasStylesXml ? MaxStylesXmlElementByteCount : 0);
            if (bufferNeeded > buffer.FreeCapacity)
            {
                await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
            }

            if (hasStylesXml)
            {
                buffer.Advance(GetStylesXmlElementBytes(worksheetPaths.Count + 1, buffer.GetSpan()));
            }

            buffer.Advance(Utf8Helper.GetBytes(Footer, buffer.GetSpan()));
            await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
        }
    }
    public static async ValueTask WriteAsync(
        ZipArchive archive,
        CompressionLevel compressionLevel,
        SpreadsheetBuffer buffer,
        CancellationToken token)
    {
        var stream = archive.CreateEntry("_rels/.rels", compressionLevel).Open();

#if NETSTANDARD2_0
        using (stream)
#else
        await using (stream.ConfigureAwait(false))
#endif
        {
            buffer.Advance(Utf8Helper.GetBytes(Content, buffer.GetSpan()));
            await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
        }
    }
示例#9
0
    public static async ValueTask WriteAsync(
        ZipArchive archive,
        CompressionLevel compressionLevel,
        SpreadsheetBuffer buffer,
        List <Style> styles,
        CancellationToken token)
    {
        var stream = archive.CreateEntry("xl/styles.xml", compressionLevel).Open();

#if NETSTANDARD2_0
        using (stream)
#else
        await using (stream.ConfigureAwait(false))
#endif
        {
            await WriteAsync(stream, buffer, styles, token).ConfigureAwait(false);
        }
    }
示例#10
0
    public static async ValueTask WriteAsync(
        ZipArchive archive,
        CompressionLevel compressionLevel,
        SpreadsheetBuffer buffer,
        List <string> worksheetPaths,
        bool hasStylesXml,
        CancellationToken token)
    {
        var stream = archive.CreateEntry("[Content_Types].xml", compressionLevel).Open();

#if NETSTANDARD2_0
        using (stream)
#else
        await using (stream.ConfigureAwait(false))
#endif
        {
            buffer.Advance(Utf8Helper.GetBytes(Header, buffer.GetSpan()));

            if (hasStylesXml)
            {
                await buffer.WriteAsciiStringAsync(Styles, stream, token).ConfigureAwait(false);
            }

            for (var i = 0; i < worksheetPaths.Count; ++i)
            {
                var path = worksheetPaths[i];
                var sheetElementLength = GetSheetElementByteCount(path);

                if (sheetElementLength > buffer.FreeCapacity)
                {
                    await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
                }

                buffer.Advance(GetSheetElementBytes(path, buffer.GetSpan()));
            }

            await buffer.WriteAsciiStringAsync(Footer, stream, token).ConfigureAwait(false);

            await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
        }
    }
示例#11
0
    public static async ValueTask WriteAsync(
        ZipArchive archive,
        CompressionLevel compressionLevel,
        SpreadsheetBuffer buffer,
        List <string> worksheetNames,
        CancellationToken token)
    {
        var stream = archive.CreateEntry("xl/workbook.xml", compressionLevel).Open();

#if NETSTANDARD2_0
        using (stream)
#else
        await using (stream.ConfigureAwait(false))
#endif
        {
            buffer.Advance(Utf8Helper.GetBytes(Header, buffer.GetSpan()));

            for (var i = 0; i < worksheetNames.Count; ++i)
            {
                var sheetId            = i + 1;
                var name               = WebUtility.HtmlEncode(worksheetNames[i]);
                var sheetElementLength = GetSheetElementByteCount(name, sheetId);

                if (sheetElementLength > buffer.FreeCapacity)
                {
                    await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
                }

                buffer.Advance(GetSheetElementBytes(name, sheetId, buffer.GetSpan()));
            }

            await buffer.WriteAsciiStringAsync(Footer, stream, token).ConfigureAwait(false);

            await buffer.FlushToStreamAsync(stream, token).ConfigureAwait(false);
        }
    }
示例#12
0
 public StyledCellWriter(SpreadsheetBuffer buffer) : base(buffer)
 {
 }
示例#13
0
 protected BaseCellWriter(SpreadsheetBuffer buffer)
 {
     Buffer = buffer;
 }
示例#14
0
 private static bool GetBytes(SpreadsheetBuffer buffer)
 {
     buffer.Advance(SpanHelper.GetBytes(DataCellHelper.NullCell, buffer.GetSpan()));
     return(true);
 }
示例#15
0
    public static async ValueTask WriteAsync(
        Stream stream,
        SpreadsheetBuffer buffer,
        Dictionary <CellReference, DataValidation> validations,
        CancellationToken token)
    {
        var sb = new StringBuilder("<dataValidations count=\"");

        sb.Append(validations.Count);
        sb.Append("\">");

        foreach (var keyValue in validations)
        {
            var validation = keyValue.Value;
            sb.Append("<dataValidation ");
            sb.AppendType(validation.Type);
            sb.AppendErrorType(validation.ErrorType);
            sb.AppendOperator(validation.Operator);

            if (validation.IgnoreBlank)
            {
                sb.Append("allowBlank=\"1\" ");
            }

            if (!validation.ShowDropdown)
            {
                sb.Append("showDropDown=\"1\" ");
            }

            if (validation.ShowInputMessage)
            {
                sb.Append("showInputMessage=\"1\" ");
            }

            if (validation.ShowErrorAlert)
            {
                sb.Append("showErrorMessage=\"1\" ");
            }

            if (!string.IsNullOrEmpty(validation.InputTitle))
            {
                sb.AppendTextAttribute("promptTitle", validation.InputTitle !);
            }

            if (!string.IsNullOrEmpty(validation.InputMessage))
            {
                sb.AppendTextAttribute("prompt", validation.InputMessage !);
            }

            if (!string.IsNullOrEmpty(validation.ErrorTitle))
            {
                sb.AppendTextAttribute("errorTitle", validation.ErrorTitle !);
            }

            if (!string.IsNullOrEmpty(validation.ErrorMessage))
            {
                sb.AppendTextAttribute("error", validation.ErrorMessage !);
            }

            sb.AppendTextAttribute("sqref", keyValue.Key.Reference);

            if (validation.Value1 is null)
            {
                sb.Append("/>");
                continue;
            }

            sb.Append("><formula1>").Append(validation.Value1).Append("</formula1>");

            if (validation.Value2 is not null)
            {
                sb.Append("<formula2>").Append(validation.Value2).Append("</formula2>");
            }

            sb.Append("</dataValidation>");
        }

        sb.Append("</dataValidations>");
        await buffer.WriteStringAsync(sb, stream, token).ConfigureAwait(false);
    }
示例#16
0
 public DataCellWriter(SpreadsheetBuffer buffer) : base(buffer)
 {
 }
示例#17
0
 private bool GetBytes(SpreadsheetBuffer buffer)
 {
     buffer.Advance(SpanHelper.GetBytes(DataCellBytes(), buffer.GetSpan()));
     return(true);
 }