Ejemplo n.º 1
0
        private static ExcelData ParseExcel(IExcelDataReader reader)
        {
            // excel 真实行列数
            var colCount = reader.FieldCount; // 减少1 = 实际数据 列
            var rowCount = reader.RowCount;   // 要减少4 = 实际数据 行

            if (!reader.Read() || colCount < 3 || rowCount < 5)
            {
                throw new Exception($"invalid sheet: {reader.Name}. colCount < 2 or rowCount < 5 or other error");
            }

            var data = new ExcelData();

            data.tablName  = reader.Name;
            data.header    = new List <ExcelData.Header>(colCount);
            data.rowValues = new List <List <string> >(rowCount - 4);

            //Console.WriteLine($"sheet: {reader.Name}  row x col = {rowCount} x {colCount}");

            for (int i = 1, n = colCount; i < n; i++)
            {
                data.header.Add(new ExcelData.Header());
            }

            int rowIndex = 0;

            do
            {
                if (rowIndex <= 3)
                {
                    for (int i = 1, n = colCount; i < n; i++)
                    {
                        var isNull = reader.IsDBNull(i);
                        if (rowIndex == 3)
                        {
                            if (isNull)
                            {
                                colCount = i;
                                //Console.WriteLine($"{data.tablName} typeName is empty. skip [{rowIndex + 1}{ConvertIntToOrderedLetter(i)}]. colCount: {colCount} i: {i}");
                                break;
                            }
                        }

                        var value = isNull ? string.Empty : reader.GetValue(i).ToString();
                        data.header[i - 1].metas[rowIndex] = value;

                        //Console.WriteLine($"[{rowIndex + 1}{ConvertIntToOrderedLetter(i)}] = {value}");
                    }

                    //Console.WriteLine($"{data.header.Count} {string.Join("\t", data.header.Select(h => h.metas[rowIndex]))}");
                }
                else
                {
                    for (int i = 1, n = colCount; i < n; i++)
                    {
                        var isNull = reader.IsDBNull(i);

                        if (i == 1)
                        {
                            if (isNull)
                            {
                                //Console.WriteLine($"{data.tablName} key is empty. skip: [{rowIndex + 1}{ConvertIntToOrderedLetter(i)}]");
                                // 第一个 key 没有值,则中断处理
                                goto END;
                            }
                            data.rowValues.Add(new List <string>(colCount - 1));
                        }

                        var value = isNull ? string.Empty : reader.GetValue(i).ToString();
                        data.rowValues[rowIndex - 4].Add(value);

                        //Console.WriteLine($"[{rowIndex + 1}{ConvertIntToOrderedLetter(i)}] = {value}");
                    }
                }

                ++rowIndex;
            }while (reader.Read());

END:


            while (data.header.Count > colCount - 1)
            {
                data.header.RemoveAt(data.header.Count - 1);
            }

            //Console.WriteLine($"sheet: {reader.Name} row x col = {rowCount} x {colCount}");

            Debug.Assert(colCount - 1 == data.header.Count, $"{data.tablName}'s colCount is invalid.");
            Debug.Assert(rowCount - 4 == data.rowValues.Count, $"{data.tablName}'s rowCount is invalid.");

            return(data);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 写入bytes
        /// </summary>
        /// <param name="data"></param>
        /// <param name="path"></param>
        internal static void WriteByteAsset(ExcelData data, string path)
        {
            //Console.WriteLine($"{data.tablName} write to {path}");

            const int MAX_ARRAY_LENGTH = 64;

            Span <byte>  bytes  = stackalloc byte[MAX_ARRAY_LENGTH];
            Span <int>   ints   = stackalloc int[MAX_ARRAY_LENGTH];
            Span <long>  longs  = stackalloc long[MAX_ARRAY_LENGTH];
            Span <float> floats = stackalloc float[MAX_ARRAY_LENGTH];

            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                BinaryWriter bw = new BinaryWriter(fs, Encoding.UTF8);

                bw.Write(TableLoader.k_DataVersion);
                bw.Write(data.rowValues.Count);//行数据长度

                var keys = new List <int>();

                for (int i = 0; i < data.rowValues.Count; i++)
                {
                    var line = data.rowValues[i];

                    keys.Clear();

                    for (int j = 0; j < data.header.Count; j++)
                    {
                        if (IgnoreHeader(data.header[j]))
                        {
                            continue;
                        }

                        if (!s_TypeLut.TryGetValue(data.header[j].fieldTypeName, out Type t))
                        {
                            throw new Exception($"type is not support. {data.tablName} col: [{j}] typeName: {data.header[j].fieldTypeName} define: {data.header[j].define}");
                        }

                        if (t == typeof(byte))
                        {
                            byte.TryParse(line[j], out byte val);
                            bw.Write(val);
                        }
                        else if (t == typeof(int))
                        {
                            var res = int.TryParse(line[j], out int val);
                            bw.Write(val);

                            if (IsKey(data.header[j]))
                            {
                                if (!res)
                                {
                                    throw new Exception($"{data.tablName} write {t} \"{line[j]}\" failed.");
                                }

                                keys.Add(val);
                            }
                        }
                        else if (t == typeof(long))
                        {
                            var res = long.TryParse(line[j], out long val);
                            bw.Write(val);

                            if (!string.IsNullOrEmpty(line[j]) && !res)
                            {
                                throw new Exception($"{data.tablName} write {t} \"{line[j]}\" failed.");
                            }
                        }
                        else if (t == typeof(float))
                        {
                            var res = float.TryParse(line[j], out float val);
                            bw.Write(val);

                            if (!string.IsNullOrEmpty(line[j]) && !res)
                            {
                                throw new Exception($"{data.tablName} write {t} \"{line[j]}\" failed.");
                            }
                        }
                        else if (t == typeof(bool))
                        {
                            var res = bool.TryParse(line[j], out bool val);
                            bw.Write(val);

                            if (!string.IsNullOrEmpty(line[j]) && !res)
                            {
                                throw new Exception($"{data.tablName} write {t} \"{line[j]}\" failed.");
                            }
                        }
                        else if (t == typeof(string))
                        {
                            bw.Write(line[j]);
                        }
                        else if (t == typeof(byte[]))
                        {
                            if (string.IsNullOrEmpty(line[j]))
                            {
                                bw.Write((byte)0);
                                continue;
                            }

                            var span = line[j].AsSpan();
                            var arr  = span.Split(',');
                            bytes.Clear();
                            byte index = 0;
                            foreach (var item in arr)
                            {
                                var chrSpan = span[item].Trim();

                                if (!byte.TryParse(chrSpan, out var val))
                                {
                                    if (!chrSpan.IsEmpty)
                                    {
                                        throw new Exception($"{data.tablName} write {t} {chrSpan.ToString()} failed.");
                                    }
                                }
                                bytes[index++] = val;
                            }

                            bw.Write(index);
                            for (int k = 0; k < index; k++)
                            {
                                bw.Write(bytes[k]);
                            }
                        }
                        else if (t == typeof(int[]))
                        {
                            if (string.IsNullOrEmpty(line[j]))
                            {
                                bw.Write((byte)0);
                                continue;
                            }

                            var span = line[j].AsSpan();
                            var arr  = span.Split(',');
                            ints.Clear();
                            byte index = 0;
                            foreach (var item in arr)
                            {
                                var chrSpan = span[item].Trim();

                                if (!int.TryParse(chrSpan, out var val))
                                {
                                    if (!chrSpan.IsEmpty)
                                    {
                                        throw new Exception($"{data.tablName} write {t} {chrSpan.ToString()} failed.");
                                    }
                                }
                                ints[index++] = val;
                            }

                            bw.Write(index);
                            for (int k = 0; k < index; k++)
                            {
                                bw.Write(ints[k]);
                            }
                        }
                        else if (t == typeof(long[]))
                        {
                            if (string.IsNullOrEmpty(line[j]))
                            {
                                bw.Write((byte)0);
                                continue;
                            }

                            var span = line[j].AsSpan();
                            var arr  = span.Split(',');
                            longs.Clear();
                            byte index = 0;
                            foreach (var item in arr)
                            {
                                var chrSpan = span[item].Trim();

                                if (!long.TryParse(chrSpan, out var val))
                                {
                                    if (!chrSpan.IsEmpty)
                                    {
                                        throw new Exception($"{data.tablName} write {t} {chrSpan.ToString()} failed.");
                                    }
                                }
                                longs[index++] = val;
                            }

                            bw.Write(index);
                            for (int k = 0; k < index; k++)
                            {
                                bw.Write(longs[k]);
                            }
                        }
                        else if (t == typeof(float[]))
                        {
                            if (string.IsNullOrEmpty(line[j]))
                            {
                                bw.Write((byte)0);
                                continue;
                            }

                            var  span  = line[j].AsSpan();
                            var  arr   = span.Split(',');
                            byte index = 0;
                            floats.Clear();
                            foreach (var item in arr)
                            {
                                var chrSpan = span[item].Trim();

                                if (!float.TryParse(chrSpan, out var val))
                                {
                                    if (!chrSpan.IsEmpty)
                                    {
                                        throw new Exception($"{data.tablName} write {t} {chrSpan.ToString()} failed.");
                                    }
                                }
                                floats[index++] = val;
                            }

                            bw.Write(index);
                            for (int k = 0; k < index; k++)
                            {
                                bw.Write(floats[k]);
                            }
                        }
                        else if (t == typeof(Dictionary <int, int>))
                        {
                            if (string.IsNullOrEmpty(line[j]))
                            {
                                bw.Write((byte)0);
                                continue;
                            }

                            var span = line[j].AsSpan();
                            var arr  = span.Split(',');
                            ints.Clear();
                            byte index = 0;
                            foreach (var item in arr)
                            {
                                var chrSpan    = span[item];
                                var splitIndex = chrSpan.IndexOf('|');

                                if (splitIndex < 0)
                                {
                                    throw new Exception("Dictionary<int,int> parse error. Required format int|int. eg. 1|2");
                                }

                                var pair0 = chrSpan.Slice(0, splitIndex).Trim();
                                var pair1 = chrSpan.Slice(splitIndex + 1).Trim();

                                if (!int.TryParse(pair0, out var val0))
                                {
                                    if (!pair0.IsEmpty)
                                    {
                                        throw new Exception($"write {t} {pair0.ToString()} failed.");
                                    }
                                }
                                ints[index++] = val0;

                                if (!int.TryParse(pair1, out var val1))
                                {
                                    if (!pair1.IsEmpty)
                                    {
                                        throw new Exception($"write {t} {pair1.ToString()} failed.");
                                    }
                                }
                                ints[index++] = val1;
                            }

                            bw.Write((byte)(index / 2));
                            for (int k = 0; k < index; k++)
                            {
                                bw.Write(ints[k]);
                            }
                        }
                    }

                    if (keys.Count < 1)
                    {
                        throw new Exception($"{data.tablName} at least 1 key");
                    }
                    else if (keys.Count > 4)
                    {
                        throw new Exception($"{data.tablName} more than 4 keys is not supportted");
                    }

                    ulong combinedKey = 0ul;
                    if (keys.Count == 1)
                    {
                        combinedKey = KeyHelper.GetKey(keys[0]);
                    }
                    else if (keys.Count == 2)
                    {
                        combinedKey = KeyHelper.GetKey(keys[0], keys[1]);
                    }
                    else if (keys.Count == 3)
                    {
                        combinedKey = KeyHelper.GetKey(keys[0], keys[1], keys[2]);
                    }
                    else if (keys.Count == 4)
                    {
                        combinedKey = KeyHelper.GetKey(keys[0], keys[1], keys[2], keys[3]);
                    }

                    bw.Write(combinedKey);
                }
                bw.Close();
            }
        }
Ejemplo n.º 3
0
        internal static void MakeCsharpFile(ExcelData excelData, string codepath)
        {
            //const string k_CsFileName = "CsvData.cs";
            //string csfile = codepath + k_CsFileName;

            var csfile = codepath;

            var sb = new StringBuilder(2048);

            var unit           = new CodeCompileUnit();
            var tableNamespace = new CodeNamespace("Saro.Table");

            unit.Namespaces.Add(tableNamespace);
            tableNamespace.Imports.Add(new CodeNamespaceImport("System.Collections"));
            tableNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
            tableNamespace.Imports.Add(new CodeNamespaceImport("System.IO"));
            tableNamespace.Imports.Add(new CodeNamespaceImport("System.Text"));

            var enumDefineList = new List <int>();

            #region item class

            var itemClass = new CodeTypeDeclaration(excelData.GetEntityClassName());
            itemClass.TypeAttributes = System.Reflection.TypeAttributes.Public | System.Reflection.TypeAttributes.Sealed;
            tableNamespace.Types.Add(itemClass);

            int index = -1;
            enumDefineList.Clear();
            foreach (var header in excelData.header)
            {
                index++;
                if (header.define == TableHelper.HeaderFilter.k_ENUM_KEY)
                {
                    enumDefineList.Add(index);
                }
                if (TableHelper.IgnoreHeader(header))
                {
                    continue;
                }

                if (!TableHelper.s_TypeLut.TryGetValue(header.fieldTypeName, out Type t))
                {
                    throw new Exception("type is not support: " + header.fieldTypeName);
                }
                var memberFiled = new CodeMemberField(t, header.fieldName);
                memberFiled.Attributes = MemberAttributes.Public;

                memberFiled.Comments.Add(new CodeCommentStatement("<summary>", true));
                memberFiled.Comments.Add(new CodeCommentStatement(header.fieldComment, true));
                memberFiled.Comments.Add(new CodeCommentStatement("</summary>", true));
                itemClass.Members.Add(memberFiled);
            }

            #endregion

            #region table class

            var tableClass = new CodeTypeDeclaration(excelData.GetWrapperClassName());
            tableClass.TypeAttributes = System.Reflection.TypeAttributes.Public | System.Reflection.TypeAttributes.Sealed;
            tableClass.BaseTypes.Add(new CodeTypeReference("BaseTable", new CodeTypeReference[] { new CodeTypeReference(excelData.GetEntityClassName()), new CodeTypeReference(excelData.GetWrapperClassName()) }));
            tableNamespace.Types.Add(tableClass);

            #region load method
            {
                var loadMethod = new CodeMemberMethod();
                tableClass.Members.Add(loadMethod);
                loadMethod.Name       = "Load";
                loadMethod.ReturnType = new CodeTypeReference(typeof(bool));
                loadMethod.Attributes = MemberAttributes.Override | MemberAttributes.Public;

                sb.AppendLine("\t\t\tif (m_Loaded) return true;");
                sb.AppendLine($"\t\t\tvar bytes = GetBytes(\"{excelData.tablName}.txt\");");
                sb.AppendLine();
                sb.AppendLine("\t\t\tusing (var ms = new MemoryStream(bytes, false))");
                sb.AppendLine("\t\t\t{");
                sb.AppendLine("\t\t\t\tusing (var br = new BinaryReader(ms))");
                sb.AppendLine("\t\t\t\t{");
                sb.AppendLine("\t\t\t\t\tvar version = br.ReadInt32();//version");
                sb.AppendLine("\t\t\t\t\tif (version != TableLoader.k_DataVersion)\n\t\t\t\t\t\tthrow new System.Exception($\"table error version. file:{version}  exe:{TableLoader.k_DataVersion}\");\n");
                sb.AppendLine("\t\t\t\t\tvar dataLen = br.ReadInt32();");
                sb.AppendLine("\t\t\t\t\tfor (int i = 0; i < dataLen; i++)");
                sb.AppendLine("\t\t\t\t\t{");
                sb.AppendLine($"\t\t\t\t\t\tvar data = new {excelData.GetEntityClassName()}();");
                bool first = true;
                foreach (var header in excelData.header)
                {
                    if (TableHelper.IgnoreHeader(header))
                    {
                        continue;
                    }

                    if (!TableHelper.s_TypeLut.TryGetValue(header.fieldTypeName, out Type t))
                    {
                        throw new Exception("type is not support: " + header.fieldTypeName);
                    }
                    if (t == typeof(byte))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadByte();");
                    }
                    else if (t == typeof(int))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadInt32();");
                    }
                    else if (t == typeof(long))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadInt64();");
                    }
                    else if (t == typeof(float))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadSingle();");
                    }
                    else if (t == typeof(bool))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadBoolean();");
                    }
                    else if (t == typeof(string))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadString();");
                    }
                    else if (t == typeof(byte[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new byte[len];");
                        sb.AppendLine($"\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadByte();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(int[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new int[len];");
                        sb.AppendLine($"\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadInt32();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(long[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new long[len];");
                        sb.AppendLine("\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadInt64();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(float[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new float[len];");
                        sb.AppendLine("\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadSingle();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(Dictionary <int, int>))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new Dictionary<int, int>(len);");
                        sb.AppendLine("\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tvar key = br.ReadInt32();");
                        sb.AppendLine($"\t\t\t\t\t\t\tvar val = br.ReadInt32();");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}.Add(key, val);");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                }
                sb.AppendLine("\t\t\t\t\t\tvar _key = br.ReadUInt64();");
                sb.AppendLine("\t\t\t\t\t\tm_Datas[_key] = data;");
                sb.AppendLine("\t\t\t\t\t}");
                sb.AppendLine("\t\t\t\t}");
                sb.AppendLine("\t\t\t}");
                sb.AppendLine("\t\t\tm_Loaded = true;");
                loadMethod.Statements.Add(new CodeSnippetStatement(sb.ToString()));
                loadMethod.Statements.Add(new CodeMethodReturnStatement(
                                              new CodeSnippetExpression("true")));

                sb.Clear();
            }
            #endregion

            #region loadasync method
            {
                var loadAsyncMethod = new CodeMemberMethod();
                tableClass.Members.Add(loadAsyncMethod);
                loadAsyncMethod.Name       = "LoadAsync";
                loadAsyncMethod.ReturnType = new CodeTypeReference("async System.Threading.Tasks.ValueTask<bool>");
                loadAsyncMethod.Attributes = MemberAttributes.Override | MemberAttributes.Public;

                sb.AppendLine("\t\t\tif (m_Loaded) return true;");
                sb.AppendLine($"\t\t\tvar bytes = await GetBytesAsync(\"{excelData.tablName}.txt\");");
                sb.AppendLine();
                sb.AppendLine("\t\t\tusing (var ms = new MemoryStream(bytes, false))");
                sb.AppendLine("\t\t\t{");
                sb.AppendLine("\t\t\t\tusing (var br = new BinaryReader(ms))");
                sb.AppendLine("\t\t\t\t{");
                sb.AppendLine("\t\t\t\t\tvar version = br.ReadInt32();//version");
                sb.AppendLine("\t\t\t\t\tif (version != TableLoader.k_DataVersion)\n\t\t\t\t\t\tthrow new System.Exception($\"table error version. file:{version}  exe:{TableLoader.k_DataVersion}\");\n");
                sb.AppendLine("\t\t\t\t\tvar dataLen = br.ReadInt32();");
                sb.AppendLine("\t\t\t\t\tfor (int i = 0; i < dataLen; i++)");
                sb.AppendLine("\t\t\t\t\t{");
                sb.AppendLine($"\t\t\t\t\t\tvar data = new {excelData.GetEntityClassName()}();");
                bool first = true;
                foreach (var header in excelData.header)
                {
                    if (TableHelper.IgnoreHeader(header))
                    {
                        continue;
                    }

                    if (!TableHelper.s_TypeLut.TryGetValue(header.fieldTypeName, out Type t))
                    {
                        throw new Exception("type is not support: " + header.fieldTypeName);
                    }
                    if (t == typeof(byte))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadByte();");
                    }
                    else if (t == typeof(int))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadInt32();");
                    }
                    else if (t == typeof(long))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadInt64();");
                    }
                    else if (t == typeof(float))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadSingle();");
                    }
                    else if (t == typeof(bool))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadBoolean();");
                    }
                    else if (t == typeof(string))
                    {
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = br.ReadString();");
                    }
                    else if (t == typeof(byte[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new byte[len];");
                        sb.AppendLine($"\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadByte();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(int[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new int[len];");
                        sb.AppendLine($"\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadInt32();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(long[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new long[len];");
                        sb.AppendLine("\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadInt64();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(float[]))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new float[len];");
                        sb.AppendLine("\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}[j] = br.ReadSingle();");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                    else if (t == typeof(Dictionary <int, int>))
                    {
                        if (first)
                        {
                            sb.AppendLine($"\t\t\t\t\t\tvar len = br.ReadByte();");
                            first = false;
                        }
                        else
                        {
                            sb.AppendLine($"\t\t\t\t\t\tlen = br.ReadByte();");
                        }
                        sb.AppendLine($"\t\t\t\t\t\tdata.{header.fieldName} = new Dictionary<int, int>(len);");
                        sb.AppendLine("\t\t\t\t\t\tfor (int j = 0; j < len; j++)");
                        sb.AppendLine("\t\t\t\t\t\t{");
                        sb.AppendLine($"\t\t\t\t\t\t\tvar key = br.ReadInt32();");
                        sb.AppendLine($"\t\t\t\t\t\t\tvar val = br.ReadInt32();");
                        sb.AppendLine($"\t\t\t\t\t\t\tdata.{header.fieldName}.Add(key, val);");
                        sb.AppendLine("\t\t\t\t\t\t}");
                    }
                }
                sb.AppendLine("\t\t\t\t\t\tvar _key = br.ReadUInt64();");
                sb.AppendLine("\t\t\t\t\t\tm_Datas[_key] = data;");
                sb.AppendLine("\t\t\t\t\t}");
                sb.AppendLine("\t\t\t\t}");
                sb.AppendLine("\t\t\t}");
                sb.AppendLine("\t\t\tm_Loaded = true;");
                loadAsyncMethod.Statements.Add(new CodeSnippetStatement(sb.ToString()));
                loadAsyncMethod.Statements.Add(new CodeMethodReturnStatement(
                                                   new CodeSnippetExpression("true")));

                sb.Clear();
            }
            #endregion

            #region query method
            {
                var keyCount        = excelData.GetKeyCount();
                var keyNames        = excelData.GetKeyNames();
                var combinedKeyName = "__combinedkey";
                if (keyCount == 1)
                {
                    sb.AppendLine($"\t\tpublic static {excelData.GetEntityClassName()} Query(int {keyNames[0]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]});");
                }
                else if (keyCount == 2)
                {
                    sb.AppendLine($"\t\tpublic static {excelData.GetEntityClassName()} Query(int {keyNames[0]}, int {keyNames[1]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]}, {keyNames[1]});");
                }
                else if (keyCount == 3)
                {
                    sb.AppendLine($"\t\tpublic static {excelData.GetEntityClassName()} Query(int {keyNames[0]}, int {keyNames[1]}, int {keyNames[2]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]}, {keyNames[1]}, {keyNames[2]});");
                }
                else if (keyCount == 4)
                {
                    sb.AppendLine($"\t\tpublic static {excelData.GetEntityClassName()} Query(int {keyNames[0]}, int {keyNames[1]}, int {keyNames[2]}, int {keyNames[3]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]}, {keyNames[1]}, {keyNames[2]}, {keyNames[3]});");
                }

                sb.AppendLine($"\t\t\tif (!Get().Load()) throw new System.Exception(\"load table failed.type: \" + nameof({excelData.GetEntityClassName()}));");
                sb.AppendLine($"\t\t\tif (Get().m_Datas.TryGetValue({combinedKeyName}, out {excelData.GetEntityClassName()} t))");
                sb.AppendLine("\t\t\t{");
                sb.AppendLine("\t\t\t\treturn t;");
                sb.AppendLine("\t\t\t}");
                sb.AppendLine($"\t\t\tthrow new System.Exception(\"null table. type: \" + nameof({excelData.GetEntityClassName()}));");
                sb.AppendLine("\t\t}");

                var queryMethod = new CodeSnippetTypeMember(sb.ToString());

                tableClass.Members.Add(queryMethod);

                sb.Clear();
            }
            #endregion


            #region queryasync method
            {
                var keyCount        = excelData.GetKeyCount();
                var keyNames        = excelData.GetKeyNames();
                var combinedKeyName = "__combinedkey";
                if (keyCount == 1)
                {
                    sb.AppendLine($"\t\tpublic static async System.Threading.Tasks.ValueTask<{excelData.GetEntityClassName()}> QueryAsync(int {keyNames[0]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]});");
                }
                else if (keyCount == 2)
                {
                    sb.AppendLine($"\t\tpublic static async System.Threading.Tasks.ValueTask<{excelData.GetEntityClassName()}> QueryAsync(int {keyNames[0]}, int {keyNames[1]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]}, {keyNames[1]});");
                }
                else if (keyCount == 3)
                {
                    sb.AppendLine($"\t\tpublic static async System.Threading.Tasks.ValueTask<{excelData.GetEntityClassName()}> QueryAsync(int {keyNames[0]}, int {keyNames[1]}, int {keyNames[2]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]}, {keyNames[1]}, {keyNames[2]});");
                }
                else if (keyCount == 4)
                {
                    sb.AppendLine($"\t\tpublic static async System.Threading.Tasks.ValueTask<{excelData.GetEntityClassName()}> QueryAsync(int {keyNames[0]}, int {keyNames[1]}, int {keyNames[2]}, int {keyNames[3]})");
                    sb.AppendLine("\t\t{");
                    sb.AppendLine($"\t\t\tvar {combinedKeyName} = KeyHelper.GetKey({keyNames[0]}, {keyNames[1]}, {keyNames[2]}, {keyNames[3]});");
                }

                sb.AppendLine($"\t\t\tvar result = await Get().LoadAsync();");
                sb.AppendLine($"\t\t\tif (!result) throw new System.Exception(\"load table failed.type: \" + nameof({excelData.GetEntityClassName()}));");
                sb.AppendLine($"\t\t\tif (Get().m_Datas.TryGetValue({combinedKeyName}, out {excelData.GetEntityClassName()} t))");
                sb.AppendLine("\t\t\t{");
                sb.AppendLine("\t\t\t\treturn t;");
                sb.AppendLine("\t\t\t}");
                sb.AppendLine($"\t\t\tthrow new System.Exception(\"null table. type: \" + nameof({excelData.GetEntityClassName()}));");
                sb.AppendLine("\t\t}");

                var queryMethod = new CodeSnippetTypeMember(sb.ToString());

                tableClass.Members.Add(queryMethod);

                sb.Clear();
            }
            #endregion


            #region PrintTable method

            var printTableMethod = new CodeMemberMethod();
            tableClass.Members.Add(printTableMethod);
            printTableMethod.Name       = "PrintTable";
            printTableMethod.ReturnType = new CodeTypeReference(typeof(string));
            printTableMethod.Attributes = MemberAttributes.Final | MemberAttributes.Public;

            sb.AppendLine("\t\t\tStringBuilder sb = null;");

            sb.AppendLine("#if ENABLE_TABLE_LOG");

            sb.AppendLine("\t\t\tsb = new StringBuilder(2048);");

            sb.AppendLine("\t\t\tforeach (var data in m_Datas.Values)");
            sb.AppendLine("\t\t\t{");
            foreach (var header in excelData.header)
            {
                if (TableHelper.IgnoreHeader(header))
                {
                    continue;
                }

                if (!TableHelper.s_TypeLut.TryGetValue(header.fieldTypeName, out Type t))
                {
                    throw new Exception("type is not support: " + header.fieldTypeName);
                }

                if (t.IsValueType ||
                    t == typeof(string))
                {
                    sb.AppendLine($"\t\t\t\tsb.Append(data.{header.fieldName}).Append(\"\\t\");");
                }
                else if (t == typeof(byte[]) ||
                         t == typeof(int[]) ||
                         t == typeof(long[]) ||
                         t == typeof(float[]))
                {
                    sb.AppendLine($"\t\t\t\tsb.Append(string.Join(\",\", data.{header.fieldName})).Append(\"\\t\");");
                }
                else if (t == typeof(Dictionary <int, int>))
                {
                    sb.AppendLine($"\t\t\t\tsb.Append(string.Join(\",\", data.{header.fieldName})).Append(\"\\t\");");
                }
            }
            sb.AppendLine("\t\t\t\tsb.AppendLine();");
            sb.AppendLine("\t\t\t}");

            sb.AppendLine("#endif");

            printTableMethod.Statements.Add(new CodeSnippetStatement(sb.ToString()));
            printTableMethod.Statements.Add(new CodeMethodReturnStatement(new CodeSnippetExpression("sb?.ToString()")));

            sb.Clear();

            #endregion

            #endregion

            #region enum define

            if (enumDefineList.Count > 0)
            {
                var enumType = new CodeTypeDeclaration(excelData.GetEnumName());
                enumType.IsEnum = true;
                tableNamespace.Types.Add(enumType);
                for (int j = 0; j < excelData.rowValues.Count; j++)
                {
                    for (int k = 0; k < enumDefineList.Count; k++)
                    {
                        sb.Append(excelData.rowValues[j][enumDefineList[k]]);
                        if (k != enumDefineList.Count - 1)
                        {
                            sb.Append("_");
                        }
                    }
                    enumType.Members.Add(new CodeMemberField()
                    {
                        Name = sb.ToString(), InitExpression = new CodePrimitiveExpression(int.Parse(excelData.rowValues[j][0]))
                    });
                    sb.Clear();
                }
            }

            #endregion

            var options = new FileStreamOptions {
                Mode = FileMode.Create, Access = FileAccess.Write, Share = FileShare.ReadWrite
            };

            var tw = new IndentedTextWriter(new StreamWriter(csfile, options), "\t");
            {
                var provider = new CSharpCodeProvider();
                tw.WriteLine("//------------------------------------------------------------------------------");
                tw.WriteLine("// File   : {0}", Path.GetFileName(codepath));
                tw.WriteLine("// Author : Saro");
                tw.WriteLine("// Time   : {0}", DateTime.Now.ToString());
                tw.WriteLine("//------------------------------------------------------------------------------");
                provider.GenerateCodeFromCompileUnit(unit, tw, new CodeGeneratorOptions()
                {
                    BracingStyle = "C"
                });
                tw.Close();
            }
        }