zhao
2021-06-24 02ca96debc6056275d58e55d97f7885a195542d0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using HH.WMS.Utils.ExcelLibrary.CompoundDocumentFormat;
using HH.WMS.Utils.ExcelLibrary.SpreadSheet;
 
namespace HH.WMS.Utils.ExcelLibrary.BinaryFileFormat
{
    public class WorkbookDecoder
    {
        public static Workbook Decode(Stream stream)
        {
            Workbook book = new Workbook();
            SharedResource sharedResource;
            List<Record> records = ReadRecords(stream, out book.DrawingGroup);
            book.Records = records;
            List<BOUNDSHEET> boundSheets = DecodeRecords(records, out sharedResource);
            foreach (BOUNDSHEET boundSheet in boundSheets)
            {
                stream.Position = boundSheet.StreamPosition;
                Worksheet sheet = WorksheetDecoder.Decode(book, stream, sharedResource);
                sheet.Book = book;
                sheet.Name = boundSheet.SheetName;
                sheet.SheetType = (SheetType)boundSheet.SheetType;
                book.Worksheets.Add(sheet);
            }
            return book;
        }
 
        private static List<Record> ReadRecords(Stream stream, out MSODRAWINGGROUP drawingGroup)
        {
            List<Record> records = new List<Record>();
            drawingGroup = null;
            Record record = Record.Read(stream);
            record.Decode();
            Record last_record = record;
            if (record is BOF && ((BOF)record).StreamType == StreamType.WorkbookGlobals)
            {
                while (record.Type != RecordType.EOF)
                {
                    if (record.Type == RecordType.CONTINUE)
                    {
                        last_record.ContinuedRecords.Add(record);
                    }
                    else
                    {
                        switch (record.Type)
                        {
                            case RecordType.MSODRAWINGGROUP:
                                if (drawingGroup == null)
                                {
                                    drawingGroup = record as MSODRAWINGGROUP;
                                    records.Add(record);
                                }
                                else
                                {
                                    drawingGroup.ContinuedRecords.Add(record);
                                }
                                break;
                            default:
                                records.Add(record);
                                break;
                        }
                        last_record = record;
                    }
                    record = Record.Read(stream);
                }
                records.Add(record);
            }
            else
            {
                throw new Exception("Invalid Workbook.");
            }
            return records;
        }
 
        private static List<BOUNDSHEET> DecodeRecords(List<Record> records, out SharedResource sharedResource)
        {
            sharedResource = new SharedResource();
            List<BOUNDSHEET> boundSheets = new List<BOUNDSHEET>();
            foreach (Record record in records)
            {
                record.Decode();
                switch (record.Type)
                {
                    case RecordType.BOUNDSHEET:
                        boundSheets.Add(record as BOUNDSHEET);
                        break;
                    case RecordType.XF:
                        sharedResource.ExtendedFormats.Add(record as XF);
                        break;
                    case RecordType.FORMAT:
                        sharedResource.CellFormats.Add(record as FORMAT);
                        break;
                    case RecordType.SST:
                        sharedResource.SharedStringTable = record as SST;
                        break;
                    case RecordType.DATEMODE:
                        DATEMODE dateMode = record as DATEMODE;
                        switch (dateMode.Mode)
                        {
                            case 0:
                                sharedResource.BaseDate = DateTime.Parse("1899-12-31");
                                break;
                            case 1:
                                sharedResource.BaseDate = DateTime.Parse("1904-01-01");
                                break;
                        }
                        break;
                    case RecordType.PALETTE:
                        PALETTE palette = record as PALETTE;
                        int colorIndex = 8;
                        foreach (int color in palette.Colors)
                        {
                            sharedResource.ColorPalette[colorIndex] = Color.FromArgb(color);
                            colorIndex++;
                        }
                        break;
                    case RecordType.FONT:
                        FONT f = record as FONT;
                        sharedResource.Fonts.Add(f);
                        break;
 
                }
            }
            return boundSheets;
        }
    }
}