/// <summary> /// 資料驗證 /// </summary> /// <param name="ValidatorPairs">資料驗證相關資訊清單(檔案,工作表,規則)</param> /// <param name="OutputFile">報告輸出路徑</param> /// <param name="OutputOptions">輸出類型:全部(Full),正確(Correct),錯誤(Error)</param> protected void Validate(IEnumerable<ValidatePair> ValidatorPairs, string OutputFile, OutputOptions OutputOptions) { #region Step1:初始化動作 //假設ValidatorPairs為0的話就不處理 if (ValidatorPairs.Count() == 0) return; if (!OutputBuilder.SameSource(ValidatorPairs,OutputOptions)) throw new Exception("目前驗證只支援ValidatePair中的DataFile需為一樣,並且OutputOptions為Full。"); //建立OutputBuilder物件,用來協助產生最後的Excel檔案 OutputBuilder outputBuilder = new OutputBuilder(ValidatorPairs, OutputFile, OutputOptions,this.ReportProgress); //建立ValidatedInfo物件,用來儲存資料驗證後的結果 ValidatedInfo validatedInfo = new ValidatedInfo(); //初始化DocumentValidate物件及事件 DocumentValidate docValidate = new DocumentValidate(); docValidate.AutoCorrect += new EventHandler<AutoCorrectEventArgs>(docValidate_AutoCorrect); docValidate.ErrorCaptured += new EventHandler<ErrorCapturedEventArgs>(docValidate_ErrorCaptured); #endregion #region Step2:進行資料驗證 foreach (ValidatePair each in ValidatorPairs) { ValidatedPair validatedPair = new ValidatedPair(); //初始化驗證訊息,在驗證每個資料表時會重新清空 RowMessages = new RowMessages(); //用來搜集資料驗證過程中的錯誤訊息, 等到資料驗證完後再一次回報錯誤訊息 Dictionary<string, Exception> exceptions = new Dictionary<string, Exception>(); List<FieldValidatedDescription> FieldDescriptions = new List<FieldValidatedDescription>(); IList<DuplicateData> DuplicateDataList = new List<DuplicateData>(); try { #region Step2.1:讀取驗證規則 docValidate.Load(each.ValidatorFile); #endregion #region Step2.2:驗證資料 //將驗證訊息都清空 RowMessages.Clear(); //將錯誤、警告及自動修正數目設為0 ErrorCount = WarningCount = AutoCorrectCount = 0; //根據目前的驗證資料組合切換 outputBuilder.Switch(each); //開始進度回報 ReportProgress(each, ErrorCount, WarningCount, AutoCorrectCount, "目前驗證: " + each.DataSheet, 0); double ValidateProgress = 0; double ValidateTotal = outputBuilder.Sheet.DataRowCount; //開始主鍵驗證 docValidate.BeginDetecteDuplicate(); #region Step2.2.1:資料驗證 SheetRowSource RowSource = new SheetRowSource(outputBuilder.Sheet); for (int i = outputBuilder.Sheet.FirstDataRowIndex; i <= outputBuilder.Sheet.DataRowCount; i++) { try { RowSource.BindRow(i); bool valid = docValidate.Validate(RowSource); RowStream RowStream = RowSource.Clone() as RowStream; //將SheetRowSource目前所指向的內容複製 validatedPair.Rows.Add(RowStream); //將RowStream加入到集合中 ReportProgress(each, ErrorCount, WarningCount, AutoCorrectCount, "目前驗證: " + each.DataSheet, (int)(++ValidateProgress * 100 / ValidateTotal)); } catch (Exception e) { ReportProgress(each, ErrorCount, WarningCount, AutoCorrectCount, "驗證錯誤: " + each.DataSheet, (int)(++ValidateProgress * 100 / ValidateTotal)); if (!exceptions.ContainsKey(e.Message)) exceptions.Add(e.Message, e); } } //exceptions.Values.ToList().ForEach(ex => SmartSchool.ErrorReporting.ReportingService.ReportException(ex)); //需要將驗證有錯誤呈現給使用者 #endregion #region Step2.2.2:主鍵驗證 DuplicateDataList = docValidate.EndDetecteDuplicate(); foreach (DuplicateData dup in DuplicateDataList) { ErrorType errorType = (dup.ErrorType == EMBA.DocumentValidator.ErrorType.Error) ? ErrorType.Error : ErrorType.Warning; foreach (DuplicateRecord dupRecord in dup) { List<string> list = new List<string>(); for (int i = 0; i < dupRecord.Values.Count; i++) list.Add(string.Format("「{0}:{1}」", dup.Fields[i], string.IsNullOrWhiteSpace(dupRecord.Values[i]) ? "缺" : dupRecord.Values[i])); string fields = (list.Count == 1 ? list[0] : string.Join("、", list.ToArray())); string msg = string.Format("{0}為鍵值,必須有資料且不得重覆。", fields); foreach (int position in dupRecord.Positions) RowMessages[position].MessageItems.Add(new MessageItem(errorType, ValidatorType.Row, msg)); } } #endregion #region Step2.2.3:欄位驗證 RowSource.BindRow(0); FieldDescriptions = docValidate.ValidateField(RowSource); string HeaderMessage = FieldDescriptions.ToDisplay(); #endregion #region Step2.2.4:客製驗證 if (CustomValidate != null) CustomValidate.Invoke(validatedPair.Rows, RowMessages); #endregion #endregion #region Step2.3:將驗證訊息寫到來源Excel outputBuilder.InitialMessageHeader(); //判斷當沒有訊息時就跳過不輸出 //if (RowMessages.Count <= 0 && string.IsNullOrEmpty(HeaderMessage)) continue; //寫入欄位驗證訊息 outputBuilder.SetHeaderMessage(HeaderMessage); //寫入資料及主鍵驗證訊息 outputBuilder.SetMessages(RowMessages); //調整驗證訊息欄寬 outputBuilder.AutoFitMessage(); #endregion } catch (Exception e) { if (!exceptions.ContainsKey(e.Message)) exceptions.Add(e.Message, e); } #region Step2.4:儲存驗證結果 validatedPair.AutoCorrectCount = RowMessages.AutoCorrectCount; validatedPair.ErrorCount = RowMessages.ErrorCount; validatedPair.WarningCount = RowMessages.WarningCount; validatedPair.DataFile = each.DataFile; validatedPair.DataSheet = each.DataSheet; validatedPair.ValidatorFile = each.ValidatorFile; validatedPair.FieldDescriptions = FieldDescriptions; validatedPair.Duplicates = DuplicateDataList; validatedPair.Exceptions = exceptions.Values.ToList(); validatedPair.UpdateMessage(); validatedInfo.ValidatedPairs.Add(validatedPair); #endregion } #endregion #region Step3:驗證報告存檔 validatedInfo.OutputFile = OutputFile; validatedInfo.OutputOptions = OutputOptions; validatedInfo.Result = outputBuilder.Sheet.Book; validatedInfo.ResultHelper = outputBuilder.Sheet; outputBuilder.Save(); #endregion #region 儲存驗證結果 if (Complete != null) Complete(validatedInfo); #endregion }
/// <summary> /// 建構式,傳入精靈參數 /// </summary> /// <param name="args"></param> public SelectImport(ArgDictionary args) : base(args) { InitializeComponent(); this.PreviousButtonVisible = false; this.NextButtonTitle = "完成"; this.NextButtonEnabled = false; //將精靈參數存起來用 mArgs = args; mImportOption = mArgs["ImportOption"] as ImportFullOption; mImportWizard = mArgs["EMBA.ImportWizard"] as ImportWizard; mValidatedInfo = mArgs["ValidatedInfo"] as ValidatedInfo; mImportName = mImportWizard.ValidateRule.Root.GetAttributeText("Name"); this.Text = mImportName + "-" + this.Text; this.Text += "(" + CurrentStep + "/" + TotalStep + ")"; //功能名稱(目前頁數/總頁數) this.txtResult.Text = "匯入中…"; this.btnViewResult.Visible = false; this.btnAgent.Visible = false; //this.TitleText += "(" + CurrentStep + "/" + TotalStep + ")"; //功能名稱(目前頁數/總頁數) }
/// <summary> /// 開始進行資料驗證 /// </summary> private void StartValidate() { //建立資料驗證組合 ValidatePair Pair = new ValidatePair(); Pair.DataFile = mImportOption.SelectedDataFile; //資料驗證來源檔案 Pair.DataSheet = mImportOption.SelectedSheetName; //資料驗證來源檔案資料表 Pair.ValidatorFile = mImportOption.SelectedValidateFile; //資料驗證描述檔 Validator.Validator valStart = new Validator.Validator(); if (mImportWizard.CustomValidate != null) { // 2012/3/7 自訂驗證規則需要使用者選取的鍵值:paul.wang mImportWizard.SelectedKeyFields = mImportOption.SelectedKeyFields; mImportWizard.SelectedFields = mImportOption.SelectedFields; valStart.CustomValidate = mImportWizard.CustomValidate; } //執行資料驗證方法 worker.DoWork += (sender, e) => valStart.Validate(Pair, mResultFilename); //將驗證過程顯示在畫面上 worker.ProgressChanged += (sender, e) => { //取得資訊物件(數量/訊息/檔名/工作表名) ValidatingPair obj = (ValidatingPair)e.UserState; //指定介面進度 pgValidProgress.Value = e.ProgressPercentage; lblProgress.Text = obj.Message; //如果錯誤大於0 if (obj.ErrorCount + obj.WarningCount + obj.AutoCorrectCount > 0) { lblErrorCount.Text = ""+obj.ErrorCount; lblWarningCount.Text = ""+obj.WarningCount; lblCorrectCount.Text = ""+obj.AutoCorrectCount; } }; //資料驗證完成 worker.RunWorkerCompleted += (sender, e) => { if (e.Error != null) throw e.Error; int ErrorText = int.Parse(lblErrorCount.Text); int WarningText = int.Parse(lblWarningCount.Text); int CorrectText = int.Parse(lblCorrectCount.Text); //若是錯誤數量為0才可進行到下一步 if (lblErrorCount.Text.Equals("0")) this.NextButtonEnabled = true; if (ErrorText >= 1) //錯誤大於1 pictureBox1.Image = EMBA.Import.Properties.Resources.filter_data_close_64; else if (WarningText >= 1) //警告大於1 pictureBox1.Image = EMBA.Import.Properties.Resources.filter_data_info_64; else //無錯誤亦無警告時 pictureBox1.Image = EMBA.Import.Properties.Resources.filter_data_ok_64; //將檢視驗證報告的按鈕啟用 btnViewResult.Enabled = true; //將可暫停非同步作業的按鈕取消 lnkCancelValid.Enabled = false; if (mValidatedInfo.ValidatedPairs[0].Exceptions.Count > 0) { string ExceptionMessage = string.Empty; foreach (Exception Exception in mValidatedInfo.ValidatedPairs[0].Exceptions) ExceptionMessage += Exception.Message + System.Environment.NewLine; if (!string.IsNullOrEmpty(ExceptionMessage)) { ExceptionMessage = "驗證過程中發生錯誤,以下為詳細錯誤訊息:" + System.Environment.NewLine + ExceptionMessage; MessageBox.Show(ExceptionMessage); } pictureBox1.Image = EMBA.Import.Properties.Resources.filter_data_close_64; this.NextButtonEnabled = false; } }; //接收資料驗證進度回報函式 valStart.Progress = (message, progress) => worker.ReportProgress(progress, message); //接收資料驗證完成函式 valStart.Complete = (message) => { mValidatedInfo = message; }; //支援非同步取消及進度回報 worker.WorkerSupportsCancellation = true; worker.WorkerReportsProgress = true; //運用非同步執行資料驗證 worker.RunWorkerAsync(); }