using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Xml;

using Excel = Microsoft.Office.Interop.Excel;

namespace CommonMP.HYMCO.OptionImpl.McStructureXmlFileEditorForDevelop
{
    /// <summary><para>class outline:</para>
    /// <para>構造定義ファイルパラメータ編集用クラス</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/11/01][新規作成]</para>
    /// </remarks>
    public class StructFileParamEditor : StructFileController
    {

        /// <summary> Excelシート名：モデル情報 </summary>
        static readonly string SHEETNAME_MODEL_MST = Properties.McStructureXmlFileEditorResources.MODEL_INFORMATION;

        /// <summary> 編集用パラメータ一覧：ヘッダー行数（1:タイトル, 2-3:表キャプション） </summary>
        private const int EDITSHEET_HEADERROW = 3;
        /// <summary> 編集用パラメータ一覧：ヘッダー列数（A:Work列,B:Key,C:Name,D:DataType） </summary>
        private const int EDITSHEET_HEADERCOL = 4;


        /// <summary>モデル名マスタ </summary>
        private Dictionary<string, string> m_csModelMst = new Dictionary<string, string>();


        /// <summary>Excelテンプレートファイルパス </summary>
        private string m_sTemplatePath = null;
        /// <summary>Excelテンプレートファイル名 </summary>
        private string m_sTemplateFile = null;


        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>StructFileParamEditor csStruct = new StructFileParamEditor(sTemplatePath, sTemplateFileName);</para>
        /// </example>
        /// <param name="sTemplatePath">Excelテンプレートファイルパス</param>
        /// <param name="sTemplateFileName">Excelテンプレートファイル名</param>
        /// <returns>StructFileParamEditor 生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public StructFileParamEditor(string sTemplatePath, string sTemplateFileName)
        {
            m_sTemplatePath = sTemplatePath;
            m_sTemplateFile = sTemplateFileName;

            //Excelテンプレートからモデルパラメータ情報を読み込む
            ReadModelMst();
        }


        #region Excelテンプレートからモデル情報読み込み

        /// <summary><para>method outline:</para>
        /// <para>Excelテンプレートからモデル情報読み込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ReadModelMst();</para>
        /// </example>
        /// <returns>無し</returns>
        /// <exception cref="System.Exception">Excelテンプレートファイル読込みに失敗</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void ReadModelMst()
        {
            ExcelController csExcel = new ExcelController();
            try
            {
                //--------------------------------------------------
                // Excelテンプレートからモデル名を読み込む
                //--------------------------------------------------
                //Excelﾃﾝﾌﾟﾚｰﾄﾌｧｲﾙｵｰﾌﾟﾝ
                csExcel.OpenBook(m_sTemplatePath + "\\" + m_sTemplateFile);

                //シート切り替え
                csExcel.SetSheet(SHEETNAME_MODEL_MST);

                int iRow = Convert.ToInt32(csExcel.GetCell(1, 1));  //データ数取得
                object[,] oVals = csExcel.GetRange(string.Format("B{0}", 3), string.Format("D{0}", iRow + 2));

                for (int j = 1; j <= iRow; j++)
                {
                    string sModelName = Convert.ToString(oVals[j, 1]);
                    string sModel = Convert.ToString(oVals[j, 2]);
                    string sFactoryID = Convert.ToString(oVals[j, 3]);
                    if (string.IsNullOrEmpty(sModel) || string.IsNullOrEmpty(sFactoryID))
                        continue;

                    string sModelKey = string.Format(StructFileController.MODEL_KEY_FORMAT, sModel, sFactoryID);
                    if (!m_csModelMst.ContainsKey(sModelKey))
                        m_csModelMst.Add(sModelKey, sModelName);
                }

            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
                //テンプレートファイル読込みでエラーが発生しました。
                throw new Exception(Properties.McStructureXmlFileEditorResources.MSG_ERROR_TEMPLATE_FILE_READ + "\n\n" + ex.Message);
            }
            finally
            {
                //Excelｱﾌﾟﾘｹｰｼｮﾝ終了
                csExcel.AppQuit();

                //COM オブジェクト解放
                csExcel.Dispose();
            }
        }
        #endregion

        #region シート書式設定

        /// <summary><para>method outline:</para>
        /// <para>シート書式設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SettingSheetFormat(csExcel, iSheetCnt);</para>
        /// </example>
        /// <param name="csExcel">ExcelController</param>
        /// <param name="iSheetCnt">シート数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void SettingSheetFormat(ExcelController csExcel, int iSheetCnt)
        {
            csExcel.SetSheet(1);

            //シート全体のフォントサイズ設定
            csExcel.SetFont(null, null, 9, false);
            //1行目の高さ設定
            csExcel.SetRowHeight(1, 1, 24);
            //列幅設定
            csExcel.SetColWidth("A", "A", 0);
            csExcel.SetColWidth("B", "B", 16);
            csExcel.SetColWidth("C", "C", 26);
            //csExcel.SetColWidth("D", "D", 8);

            //タイトルのフォント設定
            csExcel.SetFont("B1", "B1", 16, true);

            //シートコピー
            csExcel.CopySheet(iSheetCnt - 1);
        }

        #endregion

        /// <summary><para>method outline:</para>
        /// <para>パラメータ編集用Excel出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>OutputExcel(sXmlFileNamePath, sExcelFileNamePath);</para>
        /// </example>
        /// <param name="sXmlFileNamePath">構造定義ファイル名パス</param>
        /// <param name="sExcelFileNamePath">出力Excelファイル名パス</param>
        /// <returns>無し</returns>
        /// <exception cref="System.Exception">Excelファイル作成に失敗</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void OutputExcel(string sXmlFileNamePath, string sExcelFileNamePath)
        {
            ExcelController csExcel = new ExcelController();
            try
            {
                //構造定義ファイル読込み
                LoadXml(sXmlFileNamePath);
                //モデル種別ごとにグルーピングする
                GroupingCalElement();

                //モデル種類数取得
                int iSheetCnt = m_lstCalElementGroups.Count;
                
                //================================================================================
                //Excelｵｰﾌﾟﾝ
                csExcel.OpenBook();
                //シートの書式設定
                SettingSheetFormat(csExcel, iSheetCnt);
                //================================================================================

                int iHeaderRow = EDITSHEET_HEADERROW; //1:タイトル, 2-3:表キャプション
                int iHeaderCol = EDITSHEET_HEADERCOL; //A:Work列,B:Key,C:Name,D:DataType

                //モデル種別ごとのシートを作成
                int iSheetNo = 0;
                foreach (KeyValuePair<string, CalElementModelGroup> csGroups in m_lstCalElementGroups)
                {
                    iSheetNo++;
                    CalElementModelGroup csGroup = csGroups.Value;

                    //モデル名セット
                    if (m_csModelMst.ContainsKey(csGroups.Key))
                        csGroup.ModelName = m_csModelMst[csGroups.Key];

                    //同一モデル内の要素数取得
                    int iElementCount = csGroup.Items.Count;
                    //パラメータ一覧の領域確保
                    object[,] oVal = new object[iHeaderRow + csGroup.PropertyKeys.Count, iHeaderCol + iElementCount];
                    //表形式の独自パラメータ用
                    List<object[,]> lstOrig = new List<object[,]>();

                    int iElement = 0;
                    foreach (KeyValuePair<string, CalElementItem> csItem in csGroup.Items)
                    {
                        CalElementItem csElement = csItem.Value;
                        oVal[1, iHeaderCol + iElement] = csElement.ElementName;
                        oVal[2, iHeaderCol + iElement] = csElement.ID;
                        int iRow = 0;

                        //パラメータ一覧（プロパティ情報・初期状態情報）
                        foreach (KeyValuePair<string, CalElementVariable> csParam in csElement.Propertys)
                        {
                            iRow = iHeaderRow + csGroup.PropertyKeys.IndexOf(csParam.Key);
                            CalElementVariable data = csParam.Value;
                            oVal[iRow, 0] = data.TagPath;
                            oVal[iRow, 1] = data.Key;
                            oVal[iRow, 2] = data.Name;
                            oVal[iRow, 3] = data.DataType;
                            oVal[iRow, iHeaderCol + iElement] = data.Value;
                        }

                        //表形式の独自パラメータ
                        foreach (KeyValuePair<string, CalElementOriginal> csParam in csElement.OriginalPropertys)
                        {
                            object[,] oOrig = null;
                            ReadOriginal(csGroups.Key, csElement.ID, csElement.ElementName, csParam.Value, ref oOrig);

                            lstOrig.Add(oOrig);
                        }

                        iElement++;
                    }

                    //A2:モデル種別|モデルファクトリ識別子セット
                    oVal[1, 0] = csGroups.Key;
                    //B1:タイトルセット
                    oVal[0, 1] = string.Format(Properties.McStructureXmlFileEditorResources.TITLE_PARAMETER_LIST, csGroup.ModelName);
                    //一覧ヘッダ見出しセット
                    oVal[1, 1] = Properties.McStructureXmlFileEditorResources.VARIABLE_NAME;
                    oVal[2, 1] = "Key";
                    oVal[1, 2] = Properties.McStructureXmlFileEditorResources.ITEM;
                    oVal[2, 2] = "Name";
                    oVal[1, 3] = Properties.McStructureXmlFileEditorResources.TYPE;
                    oVal[2, 3] = "DataType";

                    //================================================================================
                    // パラメータ一覧セット
                    //================================================================================
                    //シート名セット
                    csExcel.SetSheet(iSheetNo);
                    csExcel.SetSheetName(string.Format("{0}{1}", iSheetNo, csGroup.ModelName));
                    //枠線
                    csExcel.SetRangeBorders("B2", csExcel.GetCellName(3, iHeaderCol + iElementCount), 36, true, false); //2～3行目：見出し
                    csExcel.SetRangeBorders("B4", csExcel.GetCellName(Math.Max(4, oVal.GetLength(0)), oVal.GetLength(1)));
                    //値セット
                    csExcel.SetCell(1, 1, oVal);                    
                    //================================================================================

                    int iRowPos = oVal.GetLength(0) + 1;

                    //================================================================================
                    // 表形式の独自パラメータセット
                    //================================================================================
                    for (int i = 0; i < lstOrig.Count; i++)
                    {
                        iRowPos++;
                        object[,] oOrig = lstOrig[i];
                        
                        csExcel.SetCell(iRowPos, 1, oOrig);
                        //枠線
                        int iTStartRow = iRowPos + 1;
                        int iTEndRow = iRowPos + oOrig.GetLength(0) - 1;
                        csExcel.SetRangeBorders(string.Format("D{0}", iTStartRow), csExcel.GetCellName(iTStartRow + 2, oOrig.GetLength(1)), 36, true, false);
                        csExcel.SetRangeBorders(string.Format("D{0}", iTStartRow + 3), csExcel.GetCellName(iTEndRow, oOrig.GetLength(1)));
                        iRowPos += oOrig.GetLength(0);
                    }
                    //================================================================================

                    //最終行に[END]をセット
                    iRowPos++;
                    csExcel.SetCell(iRowPos, 2, "[END]");
                    //※この[END]行以下は変更しないで下さい。
                    csExcel.SetCell(iRowPos, 3, Properties.McStructureXmlFileEditorResources.MSG_WARNING_NOT_CHANGE_END_LINE);
                    csExcel.SetCell(1, 1, "=MATCH(\"[END]\",B:B,0)");  //A1:使用している行数
                    csExcel.SetCellActive(1, 2);
                }


                //保存して表示
                csExcel.SaveBook(sExcelFileNamePath, false);
                csExcel.xlApp.Visible = true;
            }
            catch (Exception ex)
            {
                //Excelｱﾌﾟﾘｹｰｼｮﾝ終了
                csExcel.AppQuit();

                System.Diagnostics.Debug.WriteLine(ex);
                //編集用Excelファイル作成でエラーが発生しました。
                throw new Exception(Properties.McStructureXmlFileEditorResources.MSG_ERROR_CREATE_EXCEL_FOR_EDIT + "\n\n" + ex.Message);
            }
            finally
            {
                //COM オブジェクト解放
                csExcel.Dispose();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>構造定義ファイル出力</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bChk = OutputStructXml(sXmlFileNamePath, sExcelFileNamePath, sOutputXmlFileNamePath);</para>
        /// </example>
        /// <param name="sXmlFileNamePath">読込む構造定義ファイル名パス</param>
        /// <param name="sExcelFileNamePath">読込むExcelファイル名パス</param>
        /// <param name="sOutputXmlFileNamePath">出力構造定義ファイル名パス</param>
        /// <returns>true=正常/false=チェックエラーあり</returns>
        /// <exception cref="System.Exception">構造定義ファイル作成に失敗</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool OutputStructXml(string sXmlFileNamePath, string sExcelFileNamePath, string sOutputXmlFileNamePath)
        {
            ExcelController csExcel = new ExcelController();
            try
            {
                m_csErrorList.Clear();

                //構造定義ファイル読込み
                LoadXml(sXmlFileNamePath);
                //モデル種別ごとにグルーピングする
                GroupingCalElement();


                //================================================================================
                //Excelﾌｧｲﾙｵｰﾌﾟﾝ
                csExcel.OpenBook(sExcelFileNamePath);
                for (int iSheetNo = 1; iSheetNo <= csExcel.xlSheets.Count; iSheetNo++)
                {
                    csExcel.SetSheet(iSheetNo);
                    string sSheetName = csExcel.xlSheet.Name;
                    //A2:モデル種別|モデルファクトリ識別子 取得
                    string sModelKey = Convert.ToString(csExcel.GetCell(2, 1));

                    CalElementModelGroup csGroup = m_lstCalElementGroups[sModelKey];
                    int iRow = csGroup.PropertyKeys.Count + EDITSHEET_HEADERROW;
                    int iCol = csGroup.Items.Count + EDITSHEET_HEADERCOL;

                    //パラメータ一覧を取得（ヘッダー含む 3行,4列, ※LowerBound=1で格納されている）
                    object[,] oVal = csExcel.GetRange("A1", csExcel.GetCellName(iRow, iCol));
                    //最終行位置取得
                    int iEndRow = Convert.ToInt32(oVal[1, 1]);

                    for (int iElement = 0; iElement < csGroup.Items.Count; iElement++)
                    {   //要素（列）ごとに格納
                        iCol = EDITSHEET_HEADERCOL + iElement + 1;
                        string sID = Convert.ToString(oVal[3, iCol]);
                        //ノード取得
                        XmlElement ndCalElement = (XmlElement)m_ndlCalElement[csGroup.Items[sID].Index];
                        
                        for (int i = EDITSHEET_HEADERROW + 1; i <= oVal.GetUpperBound(0); i++)
                        {
                            string sTagPath = Convert.ToString(oVal[i, 1]);
                            string sParamKey = Convert.ToString(oVal[i, 2]);
                            string sParamVal = Convert.ToString(oVal[i, 5 + iElement]);
                            //値セット
                            SetAttributeValue(ndCalElement, sTagPath, sParamKey, sParamVal);
                        }
                    }

                    iRow += 2;
                    if (iRow >= iEndRow)
                        continue;

                    //================================================================================
                    // 表形式の独自パラメータ 取得
                    //================================================================================
                    //独自パラメータを取得（ヘッダー含む ※LowerBound=1で格納されている）
                    object[,] oOrig = csExcel.GetRange(string.Format("A{0}", iRow), csExcel.GetCellName(iEndRow, 255));
                    
                    int iR = 1;
                    while (iR <= oOrig.GetUpperBound(0))
                    {
                        string sTagPath = Convert.ToString(oOrig[iR, 1]);
                        if (sTagPath.StartsWith("*"))
                        {   //ElementID行
                            string sID = sTagPath.Substring(1);
                            string sTagPath1 = Convert.ToString(oOrig[iR + 1, 1]);
                            string sParamKey = Convert.ToString(oOrig[iR + 1, 2]);
                            string sTKey = string.Format("{0}[@Key='{1}']", sTagPath1, sParamKey);
                            
                            int iRowCount = 0;
                            for (int i = iR + 1; i <= oOrig.GetUpperBound(0); i++)
                            {   //何行あるか調べる
                                if (Convert.ToString(oOrig[i, 1]).StartsWith("*"))
                                    break;
                                iRowCount++;
                            }

                            //ノード取得
                            XmlElement ndCalElement = (XmlElement)m_ndlCalElement[csGroup.Items[sID].Index];
                            XmlElement elmParam = (XmlElement)ndCalElement.SelectSingleNode(sTKey);
                            CalElementOriginal csParam = csGroup.Items[sID].OriginalPropertys[sTKey];

                            ReadOriginal(sModelKey, elmParam, csParam, sSheetName, oOrig, iR, iRowCount);

                            iR += iRowCount;
                        }
                        iR++;
                    }

                }
                //================================================================================

                if (m_csErrorList.Count > 0)
                {   //エラーがある
                    return false;
                }

                //保存
                SaveXml(sOutputXmlFileNamePath);

                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
                //構造定義ファイル出力でエラーが発生しました。
                throw new Exception(Properties.McStructureXmlFileEditorResources.MSG_ERROR_OUTPUT_STRUCTURE_DEFINITION + "\n\n" + ex.Message);
            }
            finally
            {
                //Excelｱﾌﾟﾘｹｰｼｮﾝ終了
                csExcel.AppQuit();

                //COM オブジェクト解放
                csExcel.Dispose();
            }
        }

        /// <summary><para>method outline:</para>
        /// <para>表形式の独自パラメータ読込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ReadOriginal(sModelKey, sElementIDsElementName, csParam, ref oVal);</para>
        /// </example>
        /// <param name="sModelKey">モデルキー（モデル種別|モデルファクトリ識別子）</param>
        /// <param name="sElementID">要素ID</param>
        /// <param name="sElementName">名称</param>
        /// <param name="csParam">CalElementOriginal</param>
        /// <param name="oVal">格納用変数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void ReadOriginal(string sModelKey, string sElementID, string sElementName, CalElementOriginal csParam, ref object[,] oVal)
        {
            int iHeaderRow = 4;                                     //1:ID行,2:Name,3:Key,4:DataType
            int iStartCol = 3 + (csParam.RowNumHeader ? 1 : 0);    //A:Work列,B:Key,C:Name
            
            //領域確保
            int iRowCount = (csParam.Rows.Count == 0 ? 1 : csParam.Rows.Count);
            oVal = new object[iHeaderRow + iRowCount, iStartCol + csParam.ColCount];

            //データ取得
            for (int iR = 0; iR < iRowCount; iR++)
            {   //行
                Dictionary<string, CalElementOriginalColumn> csRow = null;
                if (iR < csParam.Rows.Count) 
                    csRow = csParam.Rows[iR];

                int iC = 0;
                if (csParam.RowNumHeader)
                {   //行No見出し
                    oVal[1, iStartCol - 1] = "No";
                    oVal[2, iStartCol - 1] = "";
                    oVal[3, iStartCol - 1] = "";
                    oVal[4 + iR, iStartCol - 1] = iR + 1;
                }
                
                List<CalElementOriginalSchema> lstOccurs = new List<CalElementOriginalSchema>();
                foreach (KeyValuePair<string, CalElementOriginalSchema> csSchema in csParam.Schemas)
                {   //列
                    CalElementOriginalSchema scm = csSchema.Value;
                    if (scm.Occurs)
                    {   //繰り返し項目の場合、まとめてNoごとに出力
                        lstOccurs.Add(scm);
                    }
                    else
                    {
                        if (lstOccurs.Count > 0)
                        {   //繰り返し項目
                            for (int iNo = csParam.MinNo; iNo <= csParam.MaxNo; iNo++)
                            {
                                for (int i = 0; i < lstOccurs.Count; i++)
                                {
                                    iC += ReadOriginalCol(csParam.AddCols, csRow, iR, iStartCol + iC, lstOccurs[i], iNo, oVal);
                                }
                            }
                            lstOccurs.Clear();
                        }

                        //繰り返さない項目
                        iC += ReadOriginalCol(csParam.AddCols, csRow, iR, iStartCol + iC, scm, 0, oVal);
                    }
                }
                if (lstOccurs.Count > 0)
                {   //繰り返し項目
                    for (int iNo = csParam.MinNo; iNo <= csParam.MaxNo; iNo++)
                    {
                        for (int i = 0; i < lstOccurs.Count; i++)
                        {
                            iC += ReadOriginalCol(csParam.AddCols, csRow, iR, iStartCol + iC, lstOccurs[i], iNo, oVal);
                        }
                    }
                }
            }


            oVal[0, 0] = string.Format("*{0}", sElementID);
            oVal[0, 1] = string.Format("【{0}：{1}】", sElementID, sElementName);
            oVal[1, 0] = csParam.TagPath;   //Tag名
            oVal[1, 1] = csParam.Key;       //変数名
            oVal[1, 2] = csParam.Name;      //項目
            if (csParam.AddRows)
            {
                oVal[2, 2] = Properties.McStructureXmlFileEditorResources.MSG_INFO_ROW_ADDITION_OK;    //※行追加可能
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>表形式の独自パラメータの列データ読込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>int iCol = ReadOriginalCol(bAddCols, csRow, iR, iC, scm, iNo, oVal);</para>
        /// </example>
        /// <param name="bAddCols">true=列追加可能</param>
        /// <param name="csRow">行データ</param>
        /// <param name="iR">行</param>
        /// <param name="iC">列</param>
        /// <param name="scm">スキーマ</param>
        /// <param name="iNo">No</param>
        /// <param name="oVal">格納用変数</param>
        /// <returns>0:対象列なし/1:対象列あり</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private int ReadOriginalCol(bool bAddCols, Dictionary<string, CalElementOriginalColumn> csRow, int iR, int iC, 
                    CalElementOriginalSchema scm, int iNo, object[,] oVal)
        {
            int iTargetColCnt = 0;
            string sValue = "";
            string sNo = string.Format("{0:#}", (scm.Occurs ? (csRow != null ? iNo : 1) : 0));
            string sColKey = string.Format("{0}|{1:#}", scm.Key, iNo);
            if (csRow != null)
            {
                if (csRow.ContainsKey(sColKey))
                {   //対象Noの列が見つかった
                    sValue = csRow[sColKey].Value;
                    iTargetColCnt = 1;
                }
            }

            if (iR == 0)
            {   //列見出し
                if (bAddCols && scm.Occurs)
                {
                    oVal[0, iC] = Properties.McStructureXmlFileEditorResources.MSG_INFO_COLUMN_ADDITION_OK;   //※列追加可能
                }
                oVal[1, iC] = scm.Name + sNo;
                oVal[2, iC] = scm.Key;
                oVal[3, iC] = scm.DataType;
            }
            oVal[4 + iR, iC] = sValue;

            return iTargetColCnt;
        }


        /// <summary><para>method outline:</para>
        /// <para>表形式の独自パラメータ読込み</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ReadOriginal(sModelKey, elmParam, csParam, sSheetName, oOrig, iStartRow, iRowCount);</para>
        /// </example>
        /// <param name="sModelKey">モデルキー（モデル種別|モデルファクトリ識別子）</param>
        /// <param name="elmParam">XmlElement</param>
        /// <param name="csParam">CalElementOriginal</param>
        /// <param name="sSheetName">Excelシート名(モデル名)</param>
        /// <param name="oOrig">Excelから読み込んだデータ</param>
        /// <param name="iStartRow">読み込み開始インデックス</param>
        /// <param name="iRowCount">行数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        private void ReadOriginal(string sModelKey, XmlElement elmParam, CalElementOriginal csParam, 
                                    string sSheetName, object[,] oOrig, int iStartRow, int iRowCount)
        {
            int iHeaderRow = 4;                                     //1:ID行,2:Name,3:Key,4:DataType
            int iStartCol = 3 + (csParam.RowNumHeader ? 1 : 0);     //A:Work列,B:Key,C:Name
            
            int iMinNo = 0;
            int iMaxNo = 0;
            List<XmlElement> lstNewRows = new List<XmlElement>();
            for (int iR = iHeaderRow + iStartRow; iR < (iStartRow + iRowCount); iR++)
            {   //行データ
                bool bNotEmpty = false;
                Dictionary<string, CalElementOriginalColumn> cols = new Dictionary<string, CalElementOriginalColumn>();
                for (int iC = iStartCol + 1; iC <= oOrig.GetUpperBound(1); iC++)
                {
                    string sName = Convert.ToString(oOrig[iStartRow + 1, iC]);
                    string sKey = Convert.ToString(oOrig[iStartRow + 2, iC]);
                    if (sName.Length == 0)
                        break;
                    
                    CalElementOriginalColumn col = new CalElementOriginalColumn();
                    col.Key = sKey;
                    col.Value = Convert.ToString(oOrig[iR, iC]);
                    col.No = 0;
                    if (col.Value.Length > 0)
                    {   //入力あり
                        bNotEmpty = true;
                    }

                    //対応するスキーマ取得
                    if (csParam.Schemas.ContainsKey(col.Key))
                    {
                        CalElementOriginalSchema scm = csParam.Schemas[col.Key];
                        if (scm.Occurs)
                        {   //繰り返し項目の場合、Noを調べる
                            foreach (KeyValuePair<string, CalElementOriginalColumn> col2 in cols)
                            {
                                if (col2.Value.Key == col.Key)
                                    col.No = Math.Max(col.No, col2.Value.No);
                            }
                            col.No++;
                        }
                        string sColKey = string.Format("{0}|{1:#}", col.Key, (scm.Occurs ? col.No : 0));
                        if (!cols.ContainsKey(sColKey))
                        {
                            cols.Add(sColKey, col);

                            iMinNo = (iMinNo == 0 ? col.No : Math.Min(iMinNo, col.No));
                            iMaxNo = (iMaxNo == 0 ? col.No : Math.Max(iMaxNo, col.No));
                        }
                        else
                        {   //繰り返し項目でないのに、同じ変数名が存在するエラー
                            //同じ変数名[ {0} ]の列があります。
                            AddError(sSheetName, 0, 0, csParam.Name, string.Format(Properties.McStructureXmlFileEditorResources.MSG_ERROR_SAME_VARIABLE_NAME_COLUMN, col.Key));
                        }
                    }
                    else
                    {   //対応するスキーマ情報なしエラー
                        //スキーマ情報にない変数名[ {0} ]の列があります。
                        AddError(sSheetName, 0, 0, "", string.Format(Properties.McStructureXmlFileEditorResources.MSG_ERROR_VARIABLE_NAME_NOT_EXIST_IN_SCHEMA, col.Key));
                    }
                }

                if (bNotEmpty)
                {
                    if (!csParam.AddCols && cols.Count != csParam.ColCount && cols.Count > 1)
                    {   //列追加不可なのに、列数が変更されているエラー
                        //この変数は列の追加はできません。
                        AddError(sSheetName, 0, 0, csParam.Name, Properties.McStructureXmlFileEditorResources.MSG_ERROR_VARIABLE_CANNOT_ADD_COLUMN);
                    }
                    else
                    {
                        XmlElement elmR = CreateOriginalRow(m_xmlDoc, csParam.Schemas, cols, iMinNo, iMaxNo);
                        lstNewRows.Add(elmR);
                    }
                }
            }

            if (!csParam.AddRows && lstNewRows.Count != csParam.Rows.Count && lstNewRows.Count > 1)
            {   //行追加不可なのに、データ行数が変更されているエラー
                //この変数はデータ行の追加はできません。
                AddError(sSheetName, 0, 0, csParam.Name, Properties.McStructureXmlFileEditorResources.MSG_ERROR_VARIABLE_CANNOT_ADD_ROW);
            }

            AppendChildNodes(elmParam, lstNewRows, "Row");
            
        }



    }
}
