浏览代码

fix 修改跨天查询数据不正确问题
优化导出速度
添加导出颜色
固定行。列
修改配置文件重複問題

jiangjy 3 周之前
父节点
当前提交
db7f86c183

+ 1 - 0
FrameworkLocal/Common/Common.csproj

@@ -571,6 +571,7 @@
     <Compile Include="Utilities\ArrayUtil.cs" />
     <Compile Include="Utilities\BinarySerializer.cs" />
     <Compile Include="Utilities\CloneUtil.cs" />
+    <Compile Include="Utilities\ColorUtil.cs" />
     <Compile Include="Utilities\CommonData.cs" />
     <Compile Include="Utilities\Converter.cs" />
     <Compile Include="Utilities\Crc16.cs" />

+ 36 - 0
FrameworkLocal/Common/Utilities/ColorUtil.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace MECF.Framework.Common.Utilities
+{
+    public class ColorUtil
+    {
+        public static string Color_Defalult = "#c9c9c9";
+        public static string Color_Yellow = "#fcff6d";
+        /// <summary>
+        /// 校验字符串是否为有效的16进制颜色代码。
+        /// 支持带#号或不带#号的格式,例如 #FFFFFF 或 FFFFFF。
+        /// </summary>
+        /// <param name="hexColor">待校验的颜色代码</param>
+        /// <returns>如果是有效的16进制颜色代码,则返回true;否则返回false。</returns>
+        public static bool IsValidHexColor(string hexColor)
+        {
+
+            if (string.IsNullOrEmpty(hexColor)) return false;
+            // 去除可能的#号
+            hexColor = hexColor.TrimStart('#');
+
+            // 检查长度是否为6(RGB)或8(ARGB)
+            if (hexColor.Length != 6 && hexColor.Length != 8) return false;
+
+            // 正则表达式匹配
+            Regex hexColorRegex = new Regex(@"^[0-9A-Fa-f]+$");
+
+            return hexColorRegex.IsMatch(hexColor);
+        }
+    }
+}

+ 5 - 0
FrameworkLocal/Common/Utilities/DateTimeUtil.cs

@@ -8,6 +8,11 @@ namespace MECF.Framework.Common.Utilities
 {
     public class DateTimeUtil
     {
+        public static string DateFormat = "yyyy/MM/dd";
+        public static string TimeFormat = "HH:mm:ss fff";
+        public static string DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
+
+
         public static float GetSecond(string timeString)
         {
             if (string.IsNullOrEmpty(timeString)) return 0;

+ 381 - 240
FrameworkLocal/UIClient/CenterViews/DataLogs/ProcessHistory/ProcessExportAllViewModel.cs

@@ -1,21 +1,19 @@
-using Aitex.Core.RT.Log;
-using Aitex.Core.UI.ControlDataContext;
-using Aitex.Core.Util;
-using Caliburn.Micro;
-using Caliburn.Micro.Core;
+using Aitex.Core.Backend;
+using Aitex.Core.RT.IOCore;
+using Aitex.Core.RT.Log;
+using DocumentFormat.OpenXml.Packaging;
 using DocumentFormat.OpenXml.Spreadsheet;
-using MECF.Framework.Common.CommonData;
 using MECF.Framework.Common.CommonData.EnumData;
 using MECF.Framework.Common.ControlDataContext;
 using MECF.Framework.Common.DataCenter;
+using MECF.Framework.Common.Equipment;
 using MECF.Framework.Common.Utilities;
 using MECF.Framework.UI.Client.CenterViews.Configs.SystemConfig;
 using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory;
 using MECF.Framework.UI.Client.CenterViews.Dialogs;
 using MECF.Framework.UI.Client.CenterViews.Operations.RealTime;
 using MECF.Framework.UI.Client.ClientBase;
-using NPOI.HSSF.UserModel;
-using NPOI.HSSF.Util;
+
 using NPOI.SS.UserModel;
 using NPOI.XSSF.UserModel;
 using OpenSEMI.ClientBase;
@@ -595,23 +593,49 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
                     }
                 }
             }
-
+            List<DataTable> pmTableList = new List<DataTable>();
+            List<DataTable> systemTableList = new List<DataTable>();
             if (StepStartTime.Date == StepEndTime.Date)
             {
+                var pmItem = GetDataTable(ModuleName.PM1, pmList, startTime, endTime);
+                pmTableList.Add(pmItem);
 
-                SaveDataToTable(fileName, pmList, systemList, startTime, endTime, recipeInfo);
+                var systemmItem = GetDataTable(ModuleName.System, systemList, startTime, endTime);
+                systemTableList.Add(systemmItem);
             }
             else
             {
                 endTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 23, 59, 59);
                 while (endTime < StepEndTime)
                 {
-                    SaveDataToTable(fileName, pmList, systemList, startTime, endTime, recipeInfo);
+                    var pmItemWhile = GetDataTable(ModuleName.PM1, pmList, startTime, endTime);
+                    pmTableList.Add(pmItemWhile);
+
+                    var systemmItemWhile = GetDataTable(ModuleName.System, systemList, startTime, endTime);
+                    systemTableList.Add(systemmItemWhile);
+
                     startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 0, 0, 0).AddDays(1);
                     endTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, 23, 59, 59);
                 }
-                SaveDataToTable(fileName, pmList, systemList, startTime, StepEndTime, recipeInfo);
+                var pmItem = GetDataTable(ModuleName.PM1, pmList, startTime, StepEndTime);
+                pmTableList.Add(pmItem);
+
+                var systemmItem = GetDataTable(ModuleName.System, systemList, startTime, StepEndTime);
+                systemTableList.Add(systemmItem);
             }
+            pmTableList = pmTableList.Where(a => a != null).ToList();
+            systemTableList = systemTableList.Where(a => a != null).ToList();
+            DataTable pm = new DataTable();
+            DataTable system = new DataTable();
+
+            if (pmTableList != null && pmTableList.Count > 0)
+                pm = MergeDataTables(pmTableList, pmTableList.FirstOrDefault().Columns.Cast<DataColumn>().Select(c => c.ColumnName).ToList());
+
+            if (systemTableList != null && systemTableList.Count > 0)
+                system = MergeDataTables(systemTableList, systemTableList.FirstOrDefault().Columns.Cast<DataColumn>().Select(c => c.ColumnName).ToList());
+
+
+            SaveDataToTable(pm, system, fileName, pmList, systemList, startTime, endTime, recipeInfo);
         }
 
         private bool firstHeader = false;
@@ -629,247 +653,160 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
         }
         public class NeedCellColor
         {
+            /// <summary>
+            /// 是否需要单元格颜色
+            /// </summary>
             public bool IsNeed;
+            /// <summary>
+            /// 配置项中的Color 数据,只支持16进制
+            /// </summary>
             public string Color;
-            public short FillForegroundColor;
-            public FillPattern FillPatternShort;
-        }
-        private ICellStyle GetICellStyle(IWorkbook workbook, NeedCellColor needCellColor = null)
-        {
-            ICellStyle cellStyle = workbook.CreateCellStyle();
-            cellStyle.WrapText = true;
-            cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
-            cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
-            cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
-            cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
-            cellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
-            cellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
-
-            if (needCellColor != null && needCellColor.IsNeed)
-            {
-                //string hexColor = needCellColor.Color;
-                //short colorIndex = GetCustomPaletteColor(workbook, hexColor);
-                cellStyle.FillForegroundColor = needCellColor.FillForegroundColor;
-                cellStyle.FillPattern = needCellColor.FillPatternShort;
-            }
-
-
-            return cellStyle;
 
         }
-        static short GetCustomPaletteColor(IWorkbook workbook, string hexColor)
+        private static System.Drawing.Color ParseHexColor(string hexColor)
         {
-            if (hexColor.StartsWith("#"))
-            {
-                hexColor = hexColor.Substring(1);
-            }
+            // 移除 #
+            hexColor = hexColor.Replace("#", "").Trim();
 
-            int red = Convert.ToInt32(hexColor.Substring(0, 2), 16);
-            int green = Convert.ToInt32(hexColor.Substring(2, 2), 16);
-            int blue = Convert.ToInt32(hexColor.Substring(4, 2), 16);
+            if (!ColorUtil.IsValidHexColor(hexColor))
+                return System.Drawing.Color.Transparent;
 
-            HSSFWorkbook hssfWorkbook = (HSSFWorkbook)workbook;
-            HSSFPalette palette = hssfWorkbook.GetCustomPalette();
 
             try
             {
-                return palette.FindSimilarColor((byte)red, (byte)green, (byte)blue).Indexed;
+                byte r = Convert.ToByte(hexColor.Substring(0, 2), 16);
+                byte g = Convert.ToByte(hexColor.Substring(2, 2), 16);
+                byte b = Convert.ToByte(hexColor.Substring(4, 2), 16);
+
+                return System.Drawing.Color.FromArgb(r, g, b);
             }
-            catch (Exception)
+            catch (Exception ex)
             {
-                // 如果找不到相似的颜色,则分配新的调色板索引
-                HSSFColor customColor = palette.FindColor((byte)red, (byte)green, (byte)blue);
-                if (customColor == null)
-                {
-                    customColor = palette.AddColor((byte)red, (byte)green, (byte)blue);
-                }
-                return customColor.Indexed;
+                return System.Drawing.Color.Transparent;
             }
         }
-        private void SaveDataToTable(string fileName, List<string> pmList, List<string> systemList, DateTime startTime, DateTime endTime, ProcessHistoryLot recipeInfo)
-        {
-            string stepID = "", stepName = "", subRecipeLoopInfo = "", subRecipeStepName = "", subRecipeStepNumber = "", tempCorrection = "", tempPid = "";
-
-            DataTable pmDataTable = null;
 
 
-            var columnsql = $"select column_name from information_schema.columns where table_name = '{startTime.ToString("yyyyMMdd")}.PM1'";
-            var columnTable = QueryDataClient.Instance.Service.QueryData(columnsql);
-            List<string> col = columnTable.Rows.Cast<DataRow>().Select(x => x.ItemArray[0].ToString()).ToList();
-            pmList = pmList.Where(x => col.Any(y => y == x)).ToList();
+        private void SaveDataToTable(DataTable pmDataTable, DataTable systemDataTable, string fileName, List<string> pmList, List<string> systemList, DateTime startTime, DateTime endTime, ProcessHistoryLot recipeInfo)
+        {
+            int numData = 35;
+            var time = DateTime.Now;
 
-            string pmsql = $"select time AS InternalTimeStamp, {string.Join(",", pmList.Select(x => string.Format("\"{0}\"", x)))}";
-            DataTable systemDataTable = null;
-            pmsql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc",
-                   startTime.ToString("yyyyMMdd") + "." + "PM1", startTime.Ticks, endTime.Ticks);
-            BusyIndicatorContent = "Example Query PM data ...";
-            pmDataTable = QueryDataClient.Instance.Service.QueryData(pmsql);
-
-
-            var sysColumnsql = $"select column_name from information_schema.columns where table_name = '{startTime.ToString("yyyyMMdd")}.System'";
-            var sysColumnTable = QueryDataClient.Instance.Service.QueryData(sysColumnsql);
-            List<string> systemCol = sysColumnTable?.Rows.Cast<DataRow>().Select(x => x.ItemArray[0].ToString()).ToList();
-            systemList = systemList.Where(x => systemCol.Any(y => y == x)).ToList();
-            string systemsql = $"select time AS InternalTimeStamp, {string.Join(",", systemList.Select(x => string.Format("\"{0}\"", x)))}";
-            systemsql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc",
-                    startTime.ToString("yyyyMMdd") + "." + "System", startTime.Ticks, endTime.Ticks);
-            BusyIndicatorContent = "Example Query System data ...";
-            systemDataTable = QueryDataClient.Instance.Service.QueryData(systemsql);
-            int maxRow = 0;
-            if ((pmDataTable == null || pmDataTable.Rows.Count == 0))
-            {
-                if (systemDataTable != null)
-                {
-                    maxRow = systemDataTable.Rows.Count;
-                }
-            }
-            else if ((systemDataTable == null || systemDataTable.Rows.Count == 0))
-            {
-                if (pmDataTable != null)
-                {
-                    maxRow = pmDataTable.Rows.Count;
-                }
-            }
-            else
-            {
-                maxRow = pmDataTable.Rows.Count > systemDataTable.Rows.Count ? systemDataTable.Rows.Count : pmDataTable.Rows.Count;
-            }
 
-            var subColNames = new List<DataColumn>() {
-                     new DataColumn("Step\nStartDate"),
-                     new DataColumn("Step\nStartTime"),
-                     new DataColumn("\tStepID\t "),
-                     new DataColumn("\tStepName\t"),
-                     new DataColumn("SubRecipe\nStepName"),
-                     new DataColumn("SubRecipe\nStepNumber"),
-                     new DataColumn("SubRecipe\nLoopInfo"),
-                     new DataColumn("Temp\nCorrection"),
-                     new DataColumn("\tTempPID\t"),
-                 };
+            string stepID = "", stepName = "", subRecipeLoopInfo = "", subRecipeStepName = "", subRecipeStepNumber = "", tempCorrection = "", tempPid = "";
 
+            int maxRow = GetMaxRow(pmDataTable, systemDataTable);
 
-            // Create a new workbook and sheet
             IWorkbook workbook = new XSSFWorkbook();
             ISheet sheet = workbook.CreateSheet("Sheet1");
-            #region style
-
+        
+            #region Recipe 信息
 
+            int rowIndex = 0;
+            int cellIndex = 0;
 
-            ICellStyle borderCellStyle = workbook.CreateCellStyle();
-            borderCellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
-            borderCellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
-            borderCellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
-            borderCellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
+            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>()
+            {
+                { "Recipe Info",recipeInfo.RecipeName},
+                { "Recipe StartTime",recipeInfo.ProcessStartTime.ToString(DateTimeUtil.DateTimeFormat)},
+                { "Recipe EndTime",recipeInfo.ProcessEndTime.ToString(DateTimeUtil.DateTimeFormat)},
+                { "Recipe Type",recipeInfo.RecipeType.ToString()},
+                { "Recipe ExecEntry",recipeInfo.RecipeExecEntry.ToString()},
+            };
 
-            IFont font = workbook.CreateFont();
+            IRow dictRow = sheet.CreateRow(0);
+            IRow dictRowTwo = sheet.CreateRow(1);
+            dictRow.HeightInPoints = numData;
+            dictRowTwo.HeightInPoints = numData;
+            foreach (var kvp in keyValuePairs)
+            {
+                var RecipeCellIndex = cellIndex++;
+                WriterCell(dictRow, RecipeCellIndex, workbook, kvp.Key, GetICellStyle(workbook));
+                WriterCell(dictRowTwo, RecipeCellIndex, workbook, kvp.Value, GetICellStyle(workbook));
 
-            borderCellStyle.SetFont(font);
-            borderCellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
-            borderCellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
+            }
             #endregion
 
 
-            int rowIndex = 4;
-            int cellIndex = 0;
+            #region 数据列表头信息
+
+            rowIndex = 4;
+            cellIndex = 0;
+
             if (!firstHeader)
             {
-                firstHeader = true;
-                var systemColNames = systemDataTable?.Columns.Cast<DataColumn>().Where(x => x.ColumnName != "internaltimestamp").Select(x =>
+                Dictionary<string, string> subColNames = new Dictionary<string, string>()
                 {
-                    if (_processProcessDetailAttributeDict.ContainsKey(x.ColumnName))
-                    {
-                        var colAttributeName = "ColName";
-                        if (!_processProcessDetailAttributeDict[x.ColumnName].ContainsKey(colAttributeName))
-                        {
-                            colAttributeName = "DisplayName";
-                        }
-                        var tempStr = _processProcessDetailAttributeDict[x.ColumnName].ContainsKey("DisplayName") && !string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName]["DisplayName"]) ? _processProcessDetailAttributeDict[x.ColumnName]["DisplayName"] : x.ColumnName;
-                        return string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName][colAttributeName]) ? x.ColumnName : _processProcessDetailAttributeDict[x.ColumnName][colAttributeName];
-                    }
-                    return x.ColumnName;
-                });
+                    { "Step\nStartDate",ColorUtil.Color_Defalult},
+                    { "Step\nStartTime",ColorUtil.Color_Defalult},
+                    { "\tStepID\t ",ColorUtil.Color_Defalult},
+                    { "\tStepName\t",ColorUtil.Color_Defalult},
+                    { "SubRecipe\nStepName",ColorUtil.Color_Defalult},
+                    { "SubRecipe\nStepNumber",ColorUtil.Color_Defalult},
+                    { "SubRecipe\nLoopInfo",ColorUtil.Color_Defalult},
+                    { "Temp\nCorrection",ColorUtil.Color_Yellow},
+                    { "\tTempPID\t",ColorUtil.Color_Yellow},
+
+                };
+
+                firstHeader = true;
+                var colColorNameDict = GetColNameColor(pmDataTable, systemDataTable);
+
+
+                var pmColorDict = colColorNameDict.Item1;
+                var systemmColorDict = colColorNameDict.Item2;
 
-                var pmColNames = pmDataTable?.Columns.Cast<DataColumn>().Where(x => x.ColumnName != "internaltimestamp").Select(x =>
-                {
-                    if (_processProcessDetailAttributeDict.ContainsKey(x.ColumnName))
-                    {
-                        var colAttributeName = "ColName";
-                        if (!_processProcessDetailAttributeDict[x.ColumnName].ContainsKey(colAttributeName))
-                        {
-                            colAttributeName = "DisplayName";
-                        }
-                        var tempStr = _processProcessDetailAttributeDict[x.ColumnName].ContainsKey("DisplayName") && !string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName]["DisplayName"]) ? _processProcessDetailAttributeDict[x.ColumnName]["DisplayName"] : x.ColumnName;
-                        return string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName][colAttributeName]) ? x.ColumnName : _processProcessDetailAttributeDict[x.ColumnName][colAttributeName];
-                    }
-                    return x.ColumnName;
-                });
 
-                // Create header row
                 IRow headerRow = sheet.CreateRow(rowIndex++);
                 cellIndex = 0;
-                headerRow.HeightInPoints = 35;
-                foreach (var subCol in subColNames)
+                headerRow.HeightInPoints = numData;
+                foreach (var item in subColNames)
                 {
-                    ICell cell = headerRow.CreateCell(cellIndex++);
-
-                    string headerText = subCol.ColumnName.Replace("(", "\n(");
-                    cell.SetCellValue(headerText);
-                    cell.CellStyle = GetICellStyle(workbook);
-                    sheet.SetColumnWidth(cell.ColumnIndex, subCol.ColumnName.Length * 256);
+                    var dataCellIndex = cellIndex++;
+                    var needCellColor = new NeedCellColor() { IsNeed = false };
+                    if (subColNames.TryGetValue(item.Key, out var dataColor) && ColorUtil.IsValidHexColor(dataColor))
+                    {
+                        needCellColor.IsNeed = true;
+                        needCellColor.Color = dataColor;
+                    }
+                    WriterCell(headerRow, dataCellIndex, workbook, item.Key.Replace("(", "\n("), GetICellStyle(workbook, needCellColor));
+                    sheet.SetColumnWidth(dataCellIndex, 22 * 256);
                 }
 
-                foreach (var sysCol in systemColNames ?? new string[0])
+                foreach (var item in systemmColorDict.Keys)
                 {
-                    ICell cell = headerRow.CreateCell(cellIndex++);
-                    string headerText = sysCol.Replace("(", "\n(");
-                    cell.SetCellValue(headerText);
-                    cell.CellStyle = GetICellStyle(workbook);
-                    sheet.SetColumnWidth(cell.ColumnIndex, sysCol.Length * 256);
+                    var dataCellIndex = cellIndex++;
+                    var needCellColor = new NeedCellColor() { IsNeed = false };
+                    if (systemmColorDict.TryGetValue(item, out var dataColor) && ColorUtil.IsValidHexColor(dataColor))
+                    {
+                        needCellColor.IsNeed = true;
+                        needCellColor.Color = dataColor;
+                    }
+                    WriterCell(headerRow, dataCellIndex, workbook, item.Replace("(", "\n("), GetICellStyle(workbook, needCellColor));
+                    sheet.SetColumnWidth(dataCellIndex, item.Length * 256);
                 }
 
-                foreach (var pmCol in pmColNames ?? new string[0])
+                foreach (var item in pmColorDict.Keys)
                 {
-                    ICell cell = headerRow.CreateCell(cellIndex++);
-                    string headerText = pmCol.Replace("(", "\n(");
-                    cell.SetCellValue(headerText);
-                    cell.CellStyle = GetICellStyle(workbook);
-                    sheet.SetColumnWidth(cell.ColumnIndex, pmCol.Length * 256);
+                    var dataCellIndex = cellIndex++;
+                    var needCellColor = new NeedCellColor() { IsNeed = false };
+                    if (pmColorDict.TryGetValue(item, out var dataColor) && ColorUtil.IsValidHexColor(dataColor))
+                    {
+                        needCellColor.IsNeed = true;
+                        needCellColor.Color = dataColor;
+                    }
+                    WriterCell(headerRow, dataCellIndex, workbook, item.Replace("(", "\n("), GetICellStyle(workbook));
+                    sheet.SetColumnWidth(dataCellIndex, item.Length * 256);
                 }
             }
+            #endregion
+
+
+            #region 数据列 行数据信息
 
-            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>()
-            {
-                { "Recipe Info",recipeInfo.RecipeName},
-                { "Recipe StartTime",recipeInfo.ProcessStartTime.ToString("yyyy-MM-dd HH:mm:ss")},
-                { "Recipe EndTime",recipeInfo.ProcessEndTime.ToString("yyyy-MM-dd HH:mm:ss")},
-                { "Recipe Type",recipeInfo.RecipeType.ToString()},
-                { "Recipe ExecEntry",recipeInfo.RecipeExecEntry.ToString()},
-            };
-            rowIndex = 0;
-            cellIndex = 0;
-            IRow dictRow = sheet.CreateRow(rowIndex);
-            dictRow.HeightInPoints = 35;
-            foreach (var kvp in keyValuePairs)
-            {
-                ICell keyCell = dictRow.CreateCell(cellIndex++);
-                keyCell.SetCellValue(kvp.Key);
-                keyCell.CellStyle = GetICellStyle(workbook);
-            }
 
-            rowIndex = 1;
-            cellIndex = 0;
-            dictRow = sheet.CreateRow(rowIndex);
-            dictRow.HeightInPoints = 35;
-            foreach (var kvp in keyValuePairs)
-            {
-                ICell keyCell = dictRow.CreateCell(cellIndex++);
-                keyCell.SetCellValue(kvp.Value);
-                keyCell.CellStyle = GetICellStyle(workbook);
-                //sheet.AutoSizeColumn(cellIndex);
-                sheet.SetColumnWidth(cellIndex - 1, kvp.Value.Length * 256);
-            }
-            int columnIndex = subColNames.Count + 1;
             rowIndex = 5;
+            _stepInfo = _stepInfo.OrderByDescending(x => x.StartTime).ToList();
 
             for (int i = 0; i < maxRow; i++)
             {
@@ -880,7 +817,7 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
 
                 DateTime dateTimeKey = new DateTime(systemRow != null ? (long)systemRow[0] : (long)pmRow[0]);
 
-                var tempStepInfo = _stepInfo.OrderByDescending(x => x.StartTime).Where(x => x.StartTime <= dateTimeKey).FirstOrDefault();
+                var tempStepInfo = _stepInfo.FirstOrDefault(x => x.StartTime <= dateTimeKey);
 
                 if (tempStepInfo != null)
                 {
@@ -895,8 +832,8 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
 
                 cellIndex = 0;
 
-                dataRow.CreateCell(cellIndex++).SetCellValue(dateTimeKey.ToString("yyyy/MM/dd"));
-                dataRow.CreateCell(cellIndex++).SetCellValue(dateTimeKey.ToString("HH:mm:ss"));
+                dataRow.CreateCell(cellIndex++).SetCellValue(dateTimeKey.ToString(DateTimeUtil.DateFormat));
+                dataRow.CreateCell(cellIndex++).SetCellValue(dateTimeKey.ToString(DateTimeUtil.TimeFormat));
                 dataRow.CreateCell(cellIndex++).SetCellValue(stepID);
                 dataRow.CreateCell(cellIndex++).SetCellValue(stepName);
                 dataRow.CreateCell(cellIndex++).SetCellValue(subRecipeStepName);
@@ -908,67 +845,271 @@ namespace MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory
                 {
                     for (int j = 1; j < systemRow.ItemArray.Length; j++)
                     {
-                        ICell cell = dataRow.CreateCell(cellIndex++);
-                        cell.SetCellValue(systemRow[j].ToString());
-                        cell.CellStyle = GetICellStyle(workbook);
+                        WriterCell(dataRow, cellIndex++, workbook, systemRow[j].ToString());
                     }
                     for (int j = 0; j < (pmDataTable?.Columns.Count ?? 0); j++)
                     {
-                        ICell cell = dataRow.CreateCell(cellIndex++);
-                        cell.SetCellValue("");
-                        cell.CellStyle = GetICellStyle(workbook);
+                        WriterCell(dataRow, cellIndex++, workbook, "");
                     }
                 }
                 else if (pmRow != null && systemRow == null)
                 {
+
                     for (int j = 0; j < (systemDataTable?.Columns?.Count ?? 0); j++)
                     {
-                        ICell cell = dataRow.CreateCell(cellIndex++);
-                        cell.SetCellValue("");
-                        cell.CellStyle = GetICellStyle(workbook);
+                        WriterCell(dataRow, cellIndex++, workbook, "");
                     }
                     for (int j = 1; j < pmRow.ItemArray.Length; j++)
                     {
-                        ICell cell = dataRow.CreateCell(cellIndex++);
-
-                        var setValueData = pmRow[j].ToString();
-                        if (bool.TryParse(pmRow[j].ToString(), out var avData))
-                            setValueData = pmRow[j].ToString() == bool.TrueString ? "Open" : "Close";
-
-                        cell.SetCellValue(setValueData);
-                        cell.CellStyle = GetICellStyle(workbook);
+                        WriterCell(dataRow, cellIndex++, workbook, ConvertBooleanValues(pmRow[j]));
                     }
                 }
                 else if (systemDataTable != null)
                 {
                     for (int j = 1; j < systemRow.ItemArray.Length; j++)
                     {
-                        ICell cell = dataRow.CreateCell(cellIndex++);
-                        cell.SetCellValue(systemRow[j].ToString());
-                        cell.CellStyle = GetICellStyle(workbook);
+                        WriterCell(dataRow, cellIndex++, workbook, systemRow[j].ToString());
                     }
                     for (int j = 1; j < pmRow.ItemArray.Length; j++)
                     {
-                        ICell cell = dataRow.CreateCell(cellIndex++);
-                        var setValueData = pmRow[j].ToString();
-                        if (bool.TryParse(pmRow[j].ToString(), out var avData))
-                            setValueData = pmRow[j].ToString() == bool.TrueString ? "Open" : "Close";
+                        WriterCell(dataRow, cellIndex++, workbook, ConvertBooleanValues(pmRow[j]));
+                    }
+                }
+            }
+            #endregion
 
-                        cell.SetCellValue(setValueData);
-                        cell.CellStyle = GetICellStyle(workbook);
+
+            sheet.CreateFreezePane(4, 5);
+
+            using (MemoryStream memoryStream = new MemoryStream())
+            {
+                workbook.Write(memoryStream);
+                File.WriteAllBytes(fileName, memoryStream.ToArray());
+            }
+        }
+
+
+
+        #region 抽离方法
+        private ICellStyle GetICellStyle(IWorkbook workbook, NeedCellColor needCellColor = null)
+        {
+            ICellStyle cellStyle = workbook.CreateCellStyle();
+            cellStyle.WrapText = true;
+            cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
+            cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
+            cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
+            cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;//粗线
+            cellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
+            cellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
+
+            if (needCellColor != null && needCellColor.IsNeed)
+            {
+                string hexColor = needCellColor.Color;
+                XSSFColor colorIndex = new XSSFColor(ParseHexColor(hexColor));
+
+                ((XSSFCellStyle)cellStyle).SetFillForegroundColor(colorIndex);
+                cellStyle.FillPattern = FillPattern.SolidForeground;
+            }
+
+
+            return cellStyle;
+
+        }
+        private string ConvertBooleanValues(object value)
+        {
+            if (bool.TryParse(value.ToString(), out bool avData))
+            {
+                return avData ? "Open" : "Close";
+            }
+            return value.ToString();
+        }
+        private DataTable MergeDataTables(List<DataTable> tables, List<string> commonColumns)
+        {
+            if (!tables.Any()) return new DataTable();
+
+            DataTable result = new DataTable();
+
+            // 添加列(确保顺序一致)
+            foreach (var colName in commonColumns)
+            {
+                var sampleCol = tables[0].Columns[colName];
+                result.Columns.Add(colName, sampleCol.DataType);
+            }
+
+            // 合并每一行
+            foreach (var table in tables)
+            {
+                foreach (DataRow row in table.Rows)
+                {
+                    var newRow = result.NewRow();
+                    foreach (var colName in commonColumns)
+                    {
+                        if (row[colName] != DBNull.Value)
+                            newRow[colName] = row[colName];
+                        else
+                            newRow[colName] = DBNull.Value;
                     }
+                    result.Rows.Add(newRow);
+                }
+            }
+            // 排序最终结果(按时间戳)
+            DataView view = result.DefaultView;
+            view.Sort = "InternalTimeStamp ASC";
+
+            return view.ToTable();
+        }
+
+        public DataTable GetDataTable(ModuleName type, List<string> queryColNameList, DateTime startTime, DateTime endTime)
+        {
+            var tableName = ModuleName.PM1.ToString();
+
+            if (type == ModuleName.System)
+                tableName = ModuleName.System.ToString();
+
+
+            DataTable resultTable = null;
+            var columnsql = $"select column_name from information_schema.columns where table_name = '{startTime.ToString("yyyyMMdd")}.{tableName}'";
+            var columnTable = QueryDataClient.Instance.Service.QueryData(columnsql);
+            List<string> col = columnTable.Rows.Cast<DataRow>().Select(x => x.ItemArray[0].ToString()).ToList();
+
+            queryColNameList = queryColNameList.Where(x => col.Any(y => y == x)).ToList();
+            var tableColName = queryColNameList.Select(x => string.Format("\"{0}\"", x));
+
+            string pmsql = $"select time AS InternalTimeStamp, {string.Join(",", tableColName)}";
+            pmsql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc",
+            startTime.ToString("yyyyMMdd") + "." + $"{tableName}", startTime.Ticks, endTime.Ticks);
+            BusyIndicatorContent = $"Example Query {tableName} data ...";
+            resultTable = QueryDataClient.Instance.Service.QueryData(pmsql);
+
+            return resultTable;
+
+        }
+        private int GetMaxRow(DataTable pmDataTable, DataTable systemDataTable)
+        {
+
+            int maxRow = 0;
+            if ((pmDataTable == null || pmDataTable.Rows.Count == 0))
+            {
+                if (systemDataTable != null)
+                {
+                    maxRow = systemDataTable.Rows.Count;
+                }
+            }
+            else if ((systemDataTable == null || systemDataTable.Rows.Count == 0))
+            {
+                if (pmDataTable != null)
+                {
+                    maxRow = pmDataTable.Rows.Count;
+                }
+            }
+            else
+            {
+                maxRow = pmDataTable.Rows.Count > systemDataTable.Rows.Count ? systemDataTable.Rows.Count : pmDataTable.Rows.Count;
+            }
+            return maxRow;
+        }
+        private Tuple<Dictionary<string, string>, Dictionary<string, string>> GetColNameColor(DataTable pmDataTable, DataTable systemDataTable)
+        {
+            Dictionary<string, string> systemColorNameDict = new Dictionary<string, string>();
+            foreach (var item in systemDataTable?.Columns.Cast<DataColumn>().Where(x => x.ColumnName != "internaltimestamp"))
+            {
+                if (!_processProcessDetailAttributeDict.ContainsKey(item.ColumnName))
+                {
+                    systemColorNameDict.Add(item.ColumnName, "");
+                    continue;
                 }
+
+
+                var colAttributeName = "ColName";
+                if (!_processProcessDetailAttributeDict[item.ColumnName].ContainsKey(colAttributeName))
+                {
+                    colAttributeName = "DisplayName";
+                }
+                var tempStr = _processProcessDetailAttributeDict[item.ColumnName].ContainsKey("DisplayName") && !string.IsNullOrEmpty(_processProcessDetailAttributeDict[item.ColumnName]["DisplayName"]) ? _processProcessDetailAttributeDict[item.ColumnName]["DisplayName"] : item.ColumnName;
+                var resultName = string.IsNullOrEmpty(_processProcessDetailAttributeDict[item.ColumnName][colAttributeName]) ? item.ColumnName : _processProcessDetailAttributeDict[item.ColumnName][colAttributeName];
+
+                colAttributeName = "Color";
+                var resultColor = "";
+                if (_processProcessDetailAttributeDict[item.ColumnName].ContainsKey(colAttributeName))
+                    resultColor = string.IsNullOrEmpty(_processProcessDetailAttributeDict[item.ColumnName][colAttributeName]) ? "" : _processProcessDetailAttributeDict[item.ColumnName][colAttributeName];
+
+                systemColorNameDict.Add(resultName, resultColor);
+
+
             }
-            sheet.SetColumnWidth(0, keyValuePairs.LastOrDefault().Key.Length * 256);
-            sheet.SetColumnWidth(3, keyValuePairs.LastOrDefault().Key.Length * 256);
-            sheet.SetColumnWidth(4, keyValuePairs.LastOrDefault().Key.Length * 256);
-            // Write the output to a file
-            using (FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write))
+            Dictionary<string, string> pmColorNameDict = new Dictionary<string, string>();
+            foreach (var item in pmDataTable?.Columns.Cast<DataColumn>().Where(x => x.ColumnName != "internaltimestamp"))
             {
-                workbook.Write(file);
+                if (!_processProcessDetailAttributeDict.ContainsKey(item.ColumnName))
+                {
+                    pmColorNameDict.Add(item.ColumnName, "");
+                    continue;
+                }
+
+
+                var colAttributeName = "ColName";
+                if (!_processProcessDetailAttributeDict[item.ColumnName].ContainsKey(colAttributeName))
+                {
+                    colAttributeName = "DisplayName";
+                }
+                var tempStr = _processProcessDetailAttributeDict[item.ColumnName].ContainsKey("DisplayName") && !string.IsNullOrEmpty(_processProcessDetailAttributeDict[item.ColumnName]["DisplayName"]) ? _processProcessDetailAttributeDict[item.ColumnName]["DisplayName"] : item.ColumnName;
+                var resultName = string.IsNullOrEmpty(_processProcessDetailAttributeDict[item.ColumnName][colAttributeName]) ? item.ColumnName : _processProcessDetailAttributeDict[item.ColumnName][colAttributeName];
+                colAttributeName = "Color";
+                var resultColor = "";
+                if (_processProcessDetailAttributeDict[item.ColumnName].ContainsKey(colAttributeName))
+                    resultColor = string.IsNullOrEmpty(_processProcessDetailAttributeDict[item.ColumnName][colAttributeName]) ? "" : _processProcessDetailAttributeDict[item.ColumnName][colAttributeName];
+
+                pmColorNameDict.Add(resultName, resultColor);
             }
+
+            return new Tuple<Dictionary<string, string>, Dictionary<string, string>>(pmColorNameDict, systemColorNameDict);
+
+        }
+        private Tuple<IEnumerable<string>, IEnumerable<string>> GetColName(DataTable pmDataTable, DataTable systemDataTable)
+        {
+
+            var systemColNames = systemDataTable?.Columns.Cast<DataColumn>().Where(x => x.ColumnName != "internaltimestamp").Select(x =>
+            {
+                if (_processProcessDetailAttributeDict.ContainsKey(x.ColumnName))
+                {
+                    var colAttributeName = "ColName";
+                    if (!_processProcessDetailAttributeDict[x.ColumnName].ContainsKey(colAttributeName))
+                    {
+                        colAttributeName = "DisplayName";
+                    }
+                    var tempStr = _processProcessDetailAttributeDict[x.ColumnName].ContainsKey("DisplayName") && !string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName]["DisplayName"]) ? _processProcessDetailAttributeDict[x.ColumnName]["DisplayName"] : x.ColumnName;
+                    return string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName][colAttributeName]) ? x.ColumnName : _processProcessDetailAttributeDict[x.ColumnName][colAttributeName];
+                }
+                return x.ColumnName;
+            });
+
+            var pmColNames = pmDataTable?.Columns.Cast<DataColumn>().Where(x => x.ColumnName != "internaltimestamp").Select(x =>
+            {
+                if (_processProcessDetailAttributeDict.ContainsKey(x.ColumnName))
+                {
+                    var colAttributeName = "ColName";
+                    if (!_processProcessDetailAttributeDict[x.ColumnName].ContainsKey(colAttributeName))
+                    {
+                        colAttributeName = "DisplayName";
+                    }
+                    var tempStr = _processProcessDetailAttributeDict[x.ColumnName].ContainsKey("DisplayName") && !string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName]["DisplayName"]) ? _processProcessDetailAttributeDict[x.ColumnName]["DisplayName"] : x.ColumnName;
+                    return string.IsNullOrEmpty(_processProcessDetailAttributeDict[x.ColumnName][colAttributeName]) ? x.ColumnName : _processProcessDetailAttributeDict[x.ColumnName][colAttributeName];
+                }
+                return x.ColumnName;
+            });
+
+            return new Tuple<IEnumerable<string>, IEnumerable<string>>(pmColNames, systemColNames);
         }
 
+        private void WriterCell(IRow row, int cellIndex, IWorkbook workbook, string setValue, ICellStyle cellStyle = null)
+        {
+            ICell keyCell = row.CreateCell(cellIndex);
+            keyCell.SetCellValue(setValue);
+            keyCell.CellStyle = cellStyle;
+
+
+        }
+        #endregion
         static string CheckAndReplace(string input)
         {
             if (input.StartsWith("PM1"))

+ 15 - 16
Furnace/FurnaceRT/Config/DisplayReplace.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <Displays>
 	<HistoryGroup name="ProcessHistory" display="Process History">
-		
+
 		<Display Name="PM1.DG1AnalogValue.Value" DisplayName="Pressure.DG1AnalogValue.Actual" />
 		<Display Name="PM1.VG11.Value" DisplayName="Pressure.VG11.Actual" />
 		<Display Name="PM1.VG21.Value" DisplayName="Pressure.VG21.Actual" />
@@ -16,17 +16,17 @@
 		<Display Name="PM1.PG6.Value" DisplayName="Pressure.PG/PS6.Actual" />
 		<Display Name="PM1.PG7.Value" DisplayName="Pressure.PG7.Actual" />
 		<Display Name="PM1.PG8.Value" DisplayName="Pressure.PG8.Actual" />
-		
+
 		<Display Name="PM1.PG12.Value" DisplayName="Pressure.PG/PS12.Actual" />
 		<Display Name="PM1.PG13.Value" DisplayName="Pressure.PG/PS13.Actual" />
 		<Display Name="PM1.PG15.Value" DisplayName="Pressure.PG/PS15.Actual" />
 		<Display Name="PM1.PG16.Value" DisplayName="Pressure.PG/PS16.Actual" />
 		<Display Name="PM1.PG70.Value" DisplayName="Pressure.PG/PS70.Actual" />
-		
+
 		<Display Name="PM1.N24PurgePressure.Value" DisplayName="Pressure.PG14.Actual" />
 		<Display Name="PM1.PS14AnalogValue.Value" DisplayName="Pressure.PS14.Actual" />
 		<Display Name="PM1.PS17.Value" DisplayName="Pressure.PS17.Actual" />
-		
+
 		<Display Name="PM1.RHCFlowFL901.Value" DisplayName="Pressure.RHCFlowFL901(FS105).Actual" />
 		<Display Name="PM1.CoolingWaterFlowOfFurnaceFL902.Value" DisplayName="Pressure.CoolingWaterFlowOfFurnaceFL902(FS106).Actual" />
 		<Display Name="PM1.CoolingWateFlowOfShuttleFL903.Value" DisplayName="Pressure.CoolingWateFlowOfShuttleFL903(FS104).Actual" />
@@ -366,11 +366,11 @@
 	</HistoryGroup>
 	<DetailGroup name="ProcessDetail" display="Process Detail">
 
-		<Display	ColName="U.Temp(act)[℃]"             Name="System.HeaterU.TempFeedback" DisplayName="Heater.U.Actual" />
-		<Display	ColName="CU.Temp(act)[℃]"             Name="System.HeaterCU.TempFeedback" DisplayName="Heater.CU.Actual" />
-		<Display	ColName="C.Temp(act)[℃]"             Name="System.HeaterC.TempFeedback" DisplayName="Heater.C.Actual" />
-		<Display	ColName="CL.Temp(act)[℃]"           Name="System.HeaterCL.TempFeedback" DisplayName="Heater.CL.Actual" />
-		<Display	ColName="L.Temp(act)[℃]"            Name="System.HeaterL.TempFeedback" DisplayName="Heater.L.Actual" />
+		<Display Color="#fcff6d" 	ColName="U.Temp(act)[℃]"             Name="System.HeaterU.TempFeedback" DisplayName="Heater.U.Actual" />
+		<Display Color="#fcff6d"	ColName="CU.Temp(act)[℃]"             Name="System.HeaterCU.TempFeedback" DisplayName="Heater.CU.Actual" />
+		<Display Color="#fcff6d"	ColName="C.Temp(act)[℃]"             Name="System.HeaterC.TempFeedback" DisplayName="Heater.C.Actual" />
+		<Display Color="#fcff6d"	ColName="CL.Temp(act)[℃]"           Name="System.HeaterCL.TempFeedback" DisplayName="Heater.CL.Actual" />
+		<Display Color="#fcff6d"	ColName="L.Temp(act)[℃]"            Name="System.HeaterL.TempFeedback" DisplayName="Heater.L.Actual" />
 
 		<Display	ColName="U.Temp(set)[℃]"             Name="System.HeaterU.TempSetPoint" DisplayName="Heater.U.Set" />
 		<Display	ColName="CU.Temp(set)[℃]"             Name="System.HeaterCU.TempSetPoint" DisplayName="Heater.CU.Set" />
@@ -384,7 +384,7 @@
 		<Display	ColName="CL.Power(act)[%]"           Name="System.HeaterCL.WorkingOutput" DisplayName="Heater.CL.Power Output" />
 		<Display	ColName="L.Power(act)[%]"            Name="System.HeaterL.WorkingOutput" DisplayName="Heater.L.Power Output" />
 
-		<Display ColName="U.Cascde(act)[℃]"           Name="System.HeaterU.CascadePV" DisplayName="Heater.U.Cascade PV" />
+		<Display   ColName="U.Cascde(act)[℃]"           Name="System.HeaterU.CascadePV" DisplayName="Heater.U.Cascade PV" />
 		<Display   ColName="CU.Cascde(act)[℃]"           Name="System.HeaterCU.CascadePV" DisplayName="Heater.CU.Cascade PV" />
 		<Display  ColName="C.Cascde(act)[℃]"           Name="System.HeaterC.CascadePV" DisplayName="Heater.C.Cascade PV" />
 		<Display   ColName="CL.Cascde(act)[℃]"         Name="System.HeaterCL.CascadePV" DisplayName="Heater.CL.Cascade PV" />
@@ -668,7 +668,7 @@
 		<Display ColName="ValveFIMS2N2Purge(act)" Name="PM1.ValveFIMS2N2Purge.Feedback" DisplayName="Valve.FIMS2 N2 Purge.Actual" />
 
 		<Display ColName="HREF(set)" Name="PM1.HREF.SetPoint" DisplayName="Valve.HREF.Set" />
-		<Display ColName="HREF(set)" Name="PM1.HREF.Feedback" DisplayName="Valve.HREF.Actual" />
+		<Display ColName="HREF(act)" Name="PM1.HREF.Feedback" DisplayName="Valve.HREF.Actual" />
 		<Display ColName="IsCEXHOn" Name="PM1.IsCEXHOn" DisplayName="Valve.IsCEXHOn" />
 		<Display ColName="IsCREFOn" Name="PM1.IsCREFOn" DisplayName="Valve.IsCREFOn" />
 		<Display ColName="IsDEPOOn" Name="PM1.IsDEPOOn" DisplayName="Valve.IsDEPOOn" />
@@ -685,12 +685,10 @@
 		<Display ColName="BothPump(set)" Name="PM1.BothPump.SetPoint" DisplayName="Valve.Both Pump.Set" />
 		<Display ColName="BothPump(act)" Name="PM1.BothPump.Feedback" DisplayName="Valve.Both Pump.Actual" />
 
-
-		<Display ColName="LoadingAreaExhaustMS321(act)" Name="PM1.LoadingAreaExhaustMS321.Value"						  DisplayName="Pressure.LoadingAreaExhaustMS321.Actual"   />
+		<Display ColName="O2(act)" Name="PM1.ConcentrationO2.Value" DisplayName="Pressure.O2.Actual" />
 		<Display ColName="PS132(act)" Name="PM1.Tank1Pressure.Value" DisplayName="Pressure.PS132.Actual" />
 		<Display ColName="PS135(act)" Name="PM1.Tank2Pressure.Value" DisplayName="Pressure.PS135.Actual" />
-		<Display ColName="O2(act)" Name="PM1.ConcentrationO2.Value" DisplayName="Pressure.O2.Actual" />
-		
+
 		<Display ColName="DG1(act)" Name="PM1.DG1AnalogValue.Value" DisplayName="Pressure.DG1AnalogValue.Actual" />
 		<Display ColName="VG11(act)" Name="PM1.VG11.Value" DisplayName="Pressure.VG11.Actual" />
 		<Display ColName="VG21(act)" Name="PM1.VG21.Value" DisplayName="Pressure.VG21.Actual" />
@@ -712,7 +710,7 @@
 		<Display ColName="PG/PS70(act)" Name="PM1.PG70.Value" DisplayName="Pressure.PG/PS70.Actual" />
 		<Display ColName="PG14(act)" Name="PM1.N24PurgePressure.Value" DisplayName="Pressure.PG14.Actual" />
 		<Display ColName="PS17(act)" Name="PM1.PS17.Value" DisplayName="Pressure.PS17.Actual" />
-		<Display ColName="RHCFlowFL901(FS105)(act)" Name="PM1.RHCFlowFL901.Value" DisplayName="Pressure.RHCFlowFL901(FS105).Actual" />
+		<Display ColName="RHCFlow(act)" Name="PM1.RHCFlowFL901.Value" DisplayName="Pressure.RHCFlowFL901(FS105).Actual" />
 		<Display ColName="CoolingWaterFlowOfFurnace(act)" Name="PM1.CoolingWaterFlowOfFurnaceFL902.Value" DisplayName="Pressure.CoolingWaterFlowOfFurnaceFL902(FS106).Actual" />
 		<Display ColName="CoolingWateFlowOfShuttle(act)" Name="PM1.CoolingWateFlowOfShuttleFL903.Value" DisplayName="Pressure.CoolingWateFlowOfShuttleFL903(FS104).Actual" />
 		<Display ColName="CoolingWaterFlowOfBoatRotation(act)" Name="PM1.CoolingWaterFlowOfBoatRotationFL904.Value" DisplayName="Pressure.CoolingWaterFlowOfBoatRotationFL904(FS111).Actual" />
@@ -723,6 +721,7 @@
 		<Display ColName="ScavengerExhaustMS3(act)" Name="PM1.ScavengerExhaustMS3.Value"				  DisplayName="Pressure.ScavengerExhaustMS3.Actual"   />
 		<Display ColName="LoadingAreaExhaustMS5(act)" Name="PM1.LoadingAreaExhaustMS5.Value"				  DisplayName="Pressure.LoadingAreaExhaustMS5.Actual"   />
 		<Display ColName="RHCExhaustMS8(act)" Name="PM1.RHCExhaustMS8.Value"						  DisplayName="Pressure.RHCExhaustMS8.Actual"   />
+		<Display ColName="LoadingAreaExhaustMS321(act)" Name="PM1.LoadingAreaExhaustMS321.Value"						  DisplayName="Pressure.LoadingAreaExhaustMS321.Actual"   />
 
 
 	</DetailGroup>