Просмотр исходного кода

重构清洁度颗粒种类选择窗体

zhangjiaxin 2 месяцев назад
Родитель
Сommit
89b335101a

+ 18 - 4
OTSIncAReportApp/1-UI/OTSReportExport/Cleanness/OTSReport_Template_CleannessA.cs

@@ -805,11 +805,20 @@ namespace OTSIncAReportApp.OTSTemplateDesigner
 
 		private void button8_Click(object sender, EventArgs e)
 		{
-	
-			RuleGroupSelector ruleGroupSelector = new RuleGroupSelector(m_OTSReport_Export.m_mbszclass.RuleGroup, m_OTSReport_Export.m_mbszclass.List_data);
+
+			//RuleGroupSelector ruleGroupSelector = new RuleGroupSelector(m_OTSReport_Export.m_mbszclass.RuleGroup, m_OTSReport_Export.m_mbszclass.List_data);
+			//ruleGroupSelector.ShowDialog();
+			//         m_OTSReport_Export.m_mbszclass.RuleGroup = ruleGroupSelector.dt.Copy();
+			//         m_OTSReport_Export.m_mbszclass.List_data = ruleGroupSelector.List_RuleTable.Copy();
+			//UpdateRuleSelectionDisplay();
+
+			GroupSelector ruleGroupSelector = new GroupSelector(m_OTSReport_Export.m_mbszclass.RuleGroup, m_OTSReport_Export.m_mbszclass.List_data);
 			ruleGroupSelector.ShowDialog();
-            m_OTSReport_Export.m_mbszclass.RuleGroup = ruleGroupSelector.dt.Copy();
-            m_OTSReport_Export.m_mbszclass.List_data = ruleGroupSelector.List_RuleTable.Copy();
+			if (ruleGroupSelector.IsConfirmed)
+			{
+				m_OTSReport_Export.m_mbszclass.RuleGroup = ruleGroupSelector.GroupSelectionInformation.Copy();
+				m_OTSReport_Export.m_mbszclass.List_data = ruleGroupSelector.ResultTables.Copy();
+			}
 			UpdateRuleSelectionDisplay();
 		}
         private void UpdateRuleSelectionDisplay()
@@ -926,5 +935,10 @@ namespace OTSIncAReportApp.OTSTemplateDesigner
 				ExportRawDataOfParticles.Add(OtsTemDRM.ExportRawDataOfParticles[i].Copy());
 			}
 		}
+
+		private void button3_Click(object sender, EventArgs e)
+		{
+			
+		}
 	}
 }

+ 145 - 0
OTSIncAReportApp/1-UI/OTSReportExport/GroupSelector.Designer.cs

@@ -0,0 +1,145 @@
+namespace OTSIncAReportApp._1_UI.OTSReportExport
+{
+	partial class GroupSelector
+	{
+		/// <summary>
+		/// Required designer variable.
+		/// </summary>
+		private System.ComponentModel.IContainer components = null;
+
+		/// <summary>
+		/// Clean up any resources being used.
+		/// </summary>
+		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+		protected override void Dispose(bool disposing)
+		{
+			if (disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Windows Form Designer generated code
+
+		/// <summary>
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// </summary>
+		private void InitializeComponent()
+		{
+			this.clbGroups = new System.Windows.Forms.CheckedListBox();
+			this.clbItems = new System.Windows.Forms.CheckedListBox();
+			this.btnConfirm = new System.Windows.Forms.Button();
+			this.label1 = new System.Windows.Forms.Label();
+			this.chkSelectAll = new System.Windows.Forms.CheckBox();
+			this.chkSelectAllAllGroups = new System.Windows.Forms.CheckBox();
+			this.button1 = new System.Windows.Forms.Button();
+			this.SuspendLayout();
+			// 
+			// clbGroups
+			// 
+			this.clbGroups.FormattingEnabled = true;
+			this.clbGroups.HorizontalScrollbar = true;
+			this.clbGroups.Location = new System.Drawing.Point(13, 33);
+			this.clbGroups.Name = "clbGroups";
+			this.clbGroups.Size = new System.Drawing.Size(180, 308);
+			this.clbGroups.TabIndex = 0;
+			this.clbGroups.SelectedIndexChanged += new System.EventHandler(this.clbGroups_SelectedIndexChanged_1);
+			// 
+			// clbItems
+			// 
+			this.clbItems.CheckOnClick = true;
+			this.clbItems.FormattingEnabled = true;
+			this.clbItems.HorizontalScrollbar = true;
+			this.clbItems.Location = new System.Drawing.Point(199, 33);
+			this.clbItems.Name = "clbItems";
+			this.clbItems.Size = new System.Drawing.Size(180, 308);
+			this.clbItems.TabIndex = 1;
+			this.clbItems.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.clbItems_ItemCheck_1);
+			// 
+			// btnConfirm
+			// 
+			this.btnConfirm.Location = new System.Drawing.Point(223, 347);
+			this.btnConfirm.Name = "btnConfirm";
+			this.btnConfirm.Size = new System.Drawing.Size(75, 23);
+			this.btnConfirm.TabIndex = 2;
+			this.btnConfirm.Text = "确认";
+			this.btnConfirm.UseVisualStyleBackColor = true;
+			this.btnConfirm.Click += new System.EventHandler(this.btnConfirm_Click);
+			// 
+			// label1
+			// 
+			this.label1.AutoSize = true;
+			this.label1.Location = new System.Drawing.Point(12, 18);
+			this.label1.Name = "label1";
+			this.label1.Size = new System.Drawing.Size(41, 12);
+			this.label1.TabIndex = 3;
+			this.label1.Text = "组信息";
+			// 
+			// chkSelectAll
+			// 
+			this.chkSelectAll.AutoSize = true;
+			this.chkSelectAll.Location = new System.Drawing.Point(289, 14);
+			this.chkSelectAll.Name = "chkSelectAll";
+			this.chkSelectAll.Size = new System.Drawing.Size(90, 16);
+			this.chkSelectAll.TabIndex = 5;
+			this.chkSelectAll.Text = "全选/全不选";
+			this.chkSelectAll.UseVisualStyleBackColor = true;
+			this.chkSelectAll.CheckStateChanged += new System.EventHandler(this.chkSelectAll_CheckStateChanged);
+			// 
+			// chkSelectAllAllGroups
+			// 
+			this.chkSelectAllAllGroups.AutoSize = true;
+			this.chkSelectAllAllGroups.Location = new System.Drawing.Point(14, 351);
+			this.chkSelectAllAllGroups.Name = "chkSelectAllAllGroups";
+			this.chkSelectAllAllGroups.Size = new System.Drawing.Size(96, 16);
+			this.chkSelectAllAllGroups.TabIndex = 6;
+			this.chkSelectAllAllGroups.Text = "全部条目全选";
+			this.chkSelectAllAllGroups.UseVisualStyleBackColor = true;
+			this.chkSelectAllAllGroups.CheckStateChanged += new System.EventHandler(this.chkSelectAllAllGroups_CheckStateChanged);
+			// 
+			// button1
+			// 
+			this.button1.Location = new System.Drawing.Point(304, 347);
+			this.button1.Name = "button1";
+			this.button1.Size = new System.Drawing.Size(75, 23);
+			this.button1.TabIndex = 7;
+			this.button1.Text = "取消";
+			this.button1.UseVisualStyleBackColor = true;
+			this.button1.Click += new System.EventHandler(this.button1_Click);
+			// 
+			// GroupSelector
+			// 
+			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+			this.ClientSize = new System.Drawing.Size(392, 374);
+			this.Controls.Add(this.button1);
+			this.Controls.Add(this.chkSelectAllAllGroups);
+			this.Controls.Add(this.chkSelectAll);
+			this.Controls.Add(this.label1);
+			this.Controls.Add(this.btnConfirm);
+			this.Controls.Add(this.clbItems);
+			this.Controls.Add(this.clbGroups);
+			this.MaximizeBox = false;
+			this.MinimizeBox = false;
+			this.Name = "GroupSelector";
+			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+			this.Text = "分组选择";
+			this.Load += new System.EventHandler(this.GroupSelector_Load);
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.CheckedListBox clbGroups;
+		private System.Windows.Forms.CheckedListBox clbItems;
+		private System.Windows.Forms.Button btnConfirm;
+		private System.Windows.Forms.Label label1;
+		private System.Windows.Forms.CheckBox chkSelectAll;
+		private System.Windows.Forms.CheckBox chkSelectAllAllGroups;
+		private System.Windows.Forms.Button button1;
+	}
+}

+ 385 - 0
OTSIncAReportApp/1-UI/OTSReportExport/GroupSelector.cs

@@ -0,0 +1,385 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Security.Policy;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace OTSIncAReportApp._1_UI.OTSReportExport
+{
+	public partial class GroupSelector : Form
+	{
+		// 原始数据源
+		private DataTable dtGroups;                     // 分组表:GroupId, GroupName, inoId, display
+		private List<DataTable> listRuleTable;          // 每个分组的条目表:StrName, display
+
+		//输出结果
+		public DataTable GroupSelectionInformation { get; set; }//每个组是否别选中
+		public List<DataTable> ResultTables { get; set; } // 每个分组的条目表:StrName, display
+		public bool IsConfirmed { get; private set; } = false; // 是否点击了确认按钮
+
+		// 运行时状态
+		private Dictionary<int, Dictionary<string, bool>> itemStates;   // GroupId -> (条目名称 -> 是否选中)
+		private Dictionary<int, List<string>> groupItems;               // GroupId -> 该分组的所有条目名称列表
+		private Dictionary<int, string> groupNames;                     // GroupId -> GroupName
+
+
+		private bool isLoading = false;      // 防止事件循环
+		private bool isSelectAllChanging = false; // 防止全选状态改变时的事件循环
+
+		public GroupSelector(DataTable groups, List<DataTable> ruleTables)
+		{
+			dtGroups = groups;
+			listRuleTable = ruleTables;
+			InitializeComponent();
+			LoadData();
+			RegisterEvents();
+			GroupSelectionInformation = new DataTable();
+			GroupSelectionInformation = groups.Clone();
+			ResultTables = new List<DataTable>();
+		}
+
+	
+
+		// 加载数据并初始化界面
+		private void LoadData()
+		{
+			if (dtGroups == null || listRuleTable == null)
+				throw new ArgumentNullException("数据源不能为空");
+
+			itemStates = new Dictionary<int, Dictionary<string, bool>>();
+			groupItems = new Dictionary<int, List<string>>();
+			groupNames = new Dictionary<int, string>();
+
+			// 先建立 GroupId 到条目表的映射(假设 listRuleTable 的顺序与 dtGroups 相同,但为安全起见按 GroupId 匹配)
+			// 由于 List_RuleTable 没有直接存储 GroupId,这里假定顺序一致且数量相等
+			if (dtGroups.Rows.Count != listRuleTable.Count)
+				MessageBox.Show("警告:分组数量与条目表数量不一致,将按顺序匹配,请确保数据正确。", "数据不一致", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+
+			for (int i = 0; i < dtGroups.Rows.Count; i++)
+			{
+				DataRow row = dtGroups.Rows[i];
+				int groupId = Convert.ToInt32(row["GroupId"]);
+				string groupName = row["GroupName"].ToString();
+				groupNames[groupId] = groupName;
+
+				// 获取对应的条目表
+				DataTable itemTable = listRuleTable[i];
+				List<string> items = new List<string>();
+				Dictionary<string, bool> states = new Dictionary<string, bool>();
+
+				foreach (DataRow itemRow in itemTable.Rows)
+				{
+					string strName = itemRow["StrName"].ToString();
+					bool display = false;
+					if (itemRow["display"].ToString() == "1")
+					{
+						display = true;
+					}
+					//bool display = Convert.ToBoolean(itemRow["display"]);
+					items.Add(strName);
+					states[strName] = display;
+				}
+
+				groupItems[groupId] = items;
+				itemStates[groupId] = states;
+
+				// 左侧添加分组(显示 GroupName,使用 GroupId 作为 Tag 以便获取)
+				int index = clbGroups.Items.Add(groupName);
+
+				if (row["display"].ToString() == "1")
+				{
+					clbGroups.SetItemChecked(index, true); 
+				}
+				
+			}
+
+			// 默认选中第一个分组
+			//if (clbGroups.Items.Count > 0)
+			//	clbGroups.SelectedIndex = 0;
+		}
+
+		// 注册事件
+		private void RegisterEvents()
+		{
+			clbGroups.SelectedIndexChanged += ClbGroups_SelectedIndexChanged;
+			clbItems.ItemCheck += ClbItems_ItemCheck;
+		}
+
+		// 左侧分组切换时,加载对应分组的条目及勾选状态
+		private void ClbGroups_SelectedIndexChanged(object sender, EventArgs e)
+		{
+			if (isLoading) return;
+			if (clbGroups.SelectedIndex < 0) return;
+
+			// 获取当前选中的 GroupId
+			int groupId = GetCurrentGroupId();
+			if (!groupItems.ContainsKey(groupId)) return;
+
+			isLoading = true;
+
+			// 清空右侧并加载当前分组的条目
+			clbItems.Items.Clear();
+			foreach (string item in groupItems[groupId])
+			{
+				bool isChecked = itemStates[groupId][item];
+				clbItems.Items.Add(item, isChecked);
+			}
+
+			isLoading = false;
+		}
+
+		// 右侧条目勾选状态改变时,更新当前分组的选中状态字典
+		private void ClbItems_ItemCheck(object sender, ItemCheckEventArgs e)
+		{
+			if (isLoading) return;
+			if (clbGroups.SelectedIndex < 0) return;
+
+			int groupId = GetCurrentGroupId();
+			string itemName = clbItems.Items[e.Index].ToString();
+
+			bool newChecked = (e.NewValue == CheckState.Checked);
+			itemStates[groupId][itemName] = newChecked;
+		}
+
+		// 获取当前选中分组的 GroupId(通过选中索引对应 dtGroups 中的行)
+		private int GetCurrentGroupId()
+		{
+			int selectedIndex = clbGroups.SelectedIndex;
+			if (selectedIndex >= 0 && selectedIndex < dtGroups.Rows.Count)
+				return Convert.ToInt32(dtGroups.Rows[selectedIndex]["GroupId"]);
+			return -1;
+		}
+
+		private void clbGroups_SelectedIndexChanged_1(object sender, EventArgs e)
+		{
+			if (isLoading) return;
+			if (clbGroups.SelectedIndex < 0) return;
+
+			int groupIndex = clbGroups.SelectedIndex;
+			if (!groupItems.ContainsKey(groupIndex)) return;
+
+			isLoading = true;
+
+			// 清空右侧并加载当前分组的条目
+			clbItems.Items.Clear();
+			foreach (string item in groupItems[groupIndex])
+			{
+				bool isChecked = itemStates[groupIndex][item];
+				clbItems.Items.Add(item, isChecked);
+			}
+
+			// 更新全选 CheckBox 状态
+			UpdateSelectAllCheckBox();
+
+			isLoading = false;
+		}
+
+		// 根据当前右侧列表的实际勾选情况,更新全选 CheckBox 的三态状态
+		private void UpdateSelectAllCheckBox()
+		{
+			if (clbItems.Items.Count == 0)
+			{
+				chkSelectAll.CheckState = CheckState.Unchecked;
+				return;
+			}
+
+			int checkedCount = 0;
+
+			
+
+			for (int i = 0; i < clbItems.Items.Count; i++)
+			{
+				if (clbItems.GetItemChecked(i))
+					checkedCount++;
+			}
+
+			if (checkedCount == 0)
+				chkSelectAll.CheckState = CheckState.Unchecked;
+			else if (checkedCount == clbItems.Items.Count)
+				chkSelectAll.CheckState = CheckState.Checked;
+			else
+				chkSelectAll.CheckState = CheckState.Indeterminate;
+		}
+
+		private void clbItems_ItemCheck_1(object sender, ItemCheckEventArgs e)
+		{
+			if (isLoading) return;
+			if (clbGroups.SelectedIndex < 0) return;
+
+
+			isSelectAllChanging = true;
+			int groupIndex = clbGroups.SelectedIndex;
+			string itemName = clbItems.Items[e.Index].ToString();
+
+			// 注意:ItemCheck 事件中无法直接获取新的勾选状态(e.NewValue),
+			// 但我们需要先更新字典,稍后刷新 CheckBox 状态时使用更新后的值。
+			// 为了避免直接修改字典导致后续更新不一致,这里暂不修改,在事件结束后统一处理。
+			// 更好的方法:延迟更新,但为了简单,我们在事件中临时计算新状态。
+			// 由于 CheckBox 状态同步需要知道更新后的字典,这里先更新字典(根据新值)。
+			bool newChecked = (e.NewValue == CheckState.Checked);
+			itemStates[groupIndex][itemName] = newChecked;
+
+			// 由于 ItemCheck 事件执行时,CheckedListBox 的勾选视觉尚未更新,
+			// 但我们的字典已经更新,接下来需要刷新全选 CheckBox 状态。
+			// 使用 BeginInvoke 延迟执行,确保界面更新完成后再同步 CheckBox 状态。
+			this.BeginInvoke(new Action(() => UpdateSelectAllCheckBox()));
+		}
+
+		private void chkSelectAll_ClientSizeChanged(object sender, EventArgs e)
+		{
+
+		}
+
+		private void btnConfirm_Click(object sender, EventArgs e)
+		{
+			GroupSelectionInformation=new DataTable();
+			GroupSelectionInformation = dtGroups.Clone();
+			ResultTables = new List<DataTable>();
+			for (int i = 0; i < dtGroups.Rows.Count; i++)
+			{
+				GroupSelectionInformation.Rows.Add(dtGroups.Rows[i].ItemArray);
+
+				DataTable dataTable = listRuleTable[i].Copy();
+				int GroupId = Convert.ToInt32(dtGroups.Rows[i]["GroupId"]);
+				DataTable dt= new DataTable();
+				dt.Columns.Add("StrName", typeof(string));
+				dt.Columns.Add("display", typeof(int));
+				// 按照原始顺序添加所有条目,并设置最新的 display 状态
+				foreach (string itemName in groupItems[GroupId])
+				{
+					bool isChecked = itemStates[GroupId][itemName];
+					DataRow dr = dt.NewRow();
+					dr["StrName"] = itemName;
+					if (isChecked)
+						dr["display"] = 1;
+					else
+						dr["display"] = 0;
+					dt.Rows.Add(dr);
+				}
+				for (int a = 0; a < dataTable.Rows.Count; a++)
+				{
+					for (int j = 0; j < dt.Rows.Count; j++)
+					{
+						if (dataTable.Rows[a]["StrName"].ToString() == dt.Rows[j]["StrName"].ToString())
+						{
+							dataTable.Rows[a]["display"] = dt.Rows[j]["display"].ToString();
+						}
+					}
+				}
+				ResultTables.Add(dataTable);
+			}
+
+			for (int i = 0; i < clbGroups.Items.Count; i++)
+			{
+				if (clbGroups.GetItemChecked(i))
+				{
+					GroupSelectionInformation.Rows[i]["display"] = "1";
+				}
+				else
+				{
+					GroupSelectionInformation.Rows[i]["display"] = "0";
+				}
+			}
+			IsConfirmed= true;
+			this.Close();
+		}
+
+
+		private void chkSelectAll_CheckStateChanged(object sender, EventArgs e)
+		{
+			if (!isSelectAllChanging)
+			{
+				for (int i = 0; i < clbItems.Items.Count; i++)
+				{
+					clbItems.SetItemChecked(i, chkSelectAll.Checked);
+				}
+			};
+			isSelectAllChanging = false;
+		}
+
+		private void GroupSelector_Load(object sender, EventArgs e)
+		{
+			// 清空右侧并加载当前分组的条目
+			//clbItems.Items.Clear();
+
+			// 默认选中第一个分组
+			if (clbGroups.Items.Count > 0)
+				clbGroups.SelectedIndex = 0;
+		}
+
+		private void UpdateAllGroupsSelectAllCheckBox()
+		{
+			if (groupItems.Count == 0)
+			{
+				chkSelectAllAllGroups.CheckState = CheckState.Unchecked;
+				return;
+			}
+
+			int totalItems = 0;
+			int totalChecked = 0;
+			foreach (var kvp in itemStates)
+			{
+				var states = kvp.Value;
+				totalItems += states.Count;
+				foreach (var itemState in states)
+				{
+					if (itemState.Value) totalChecked++;
+				}
+			}
+
+			if (totalChecked == 0)
+				chkSelectAllAllGroups.CheckState = CheckState.Unchecked;
+			else if (totalChecked == totalItems)
+				chkSelectAllAllGroups.CheckState = CheckState.Checked;
+			else
+				chkSelectAllAllGroups.CheckState = CheckState.Indeterminate;
+		}
+
+		private void chkSelectAllAllGroups_CheckStateChanged(object sender, EventArgs e)
+		{
+			if (isLoading) return;
+			bool shouldCheckAll = (chkSelectAllAllGroups.CheckState == CheckState.Checked);
+
+			isLoading = true;
+
+			// 更新所有分组的条目状态
+			foreach (var groupIndex in groupItems.Keys)
+			{
+				var items = groupItems[groupIndex];
+				foreach (string itemName in items)
+				{
+					itemStates[groupIndex][itemName] = shouldCheckAll;
+				}
+			}
+
+			// 刷新当前显示的右侧列表界面
+			int currentGroup = clbGroups.SelectedIndex;
+			if (currentGroup >= 0 && groupItems.ContainsKey(currentGroup))
+			{
+				for (int i = 0; i < clbItems.Items.Count; i++)
+				{
+					string itemName = clbItems.Items[i].ToString();
+					clbItems.SetItemChecked(i, shouldCheckAll);
+				}
+			}
+
+			// 更新右侧全选 CheckBox 的状态
+			UpdateSelectAllCheckBox();
+			for (int i = 0; i < clbGroups.Items.Count; i++)
+			{
+				clbGroups.SetItemChecked(i, chkSelectAllAllGroups.Checked);
+			}
+			isLoading = false;
+		}
+
+		private void button1_Click(object sender, EventArgs e)
+		{
+			this.Close();
+		}
+	}
+}

+ 120 - 0
OTSIncAReportApp/1-UI/OTSReportExport/GroupSelector.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 9 - 0
OTSIncAReportApp/OTSIncAReportApp.csproj

@@ -584,6 +584,12 @@
     <Compile Include="1-UI\OTSReportExport\DataIntegration\ExportSelectionForm.Designer.cs">
       <DependentUpon>ExportSelectionForm.cs</DependentUpon>
     </Compile>
+    <Compile Include="1-UI\OTSReportExport\GroupSelector.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="1-UI\OTSReportExport\GroupSelector.Designer.cs">
+      <DependentUpon>GroupSelector.cs</DependentUpon>
+    </Compile>
     <Compile Include="2-CommonFunction\CommonClass\ElementSubscript.cs" />
     <Compile Include="1-UI\FormStandardLibraryInformation.cs">
       <SubType>Form</SubType>
@@ -1040,6 +1046,9 @@
     <EmbeddedResource Include="1-UI\OTSReportExport\ExportYB6156Preview.resx">
       <DependentUpon>ExportYB6156Preview.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="1-UI\OTSReportExport\GroupSelector.resx">
+      <DependentUpon>GroupSelector.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="1-UI\OTSReportExport\RuleGroupSelector.resx">
       <DependentUpon>RuleGroupSelector.cs</DependentUpon>
     </EmbeddedResource>