| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 2025-08-15 kyy 快速配置GridView条件汇总(只汇总满足条件的行) |
| | | /// 使用简单的标签显示方式,避免复杂的汇总项配置 |
| | | /// </summary> |
| | | /// <param name="gridView">目标GridView控件</param> |
| | | /// <param name="conditionFieldName">条件字段名(如chkInt)</param> |
| | | /// <param name="conditionValue">条件值(如true、1等表示选中)</param> |
| | | /// <param name="summaryColumns">需要进行求和汇总的列名数组</param> |
| | | public static void SetupGridSummaryWithCondition(DevExpress.XtraGrid.Views.Grid.GridView gridView, string conditionFieldName, object conditionValue, params string[] summaryColumns) |
| | | { |
| | | // 启用底部汇总行 |
| | | gridView.OptionsView.ShowFooter = true; |
| | | |
| | | // 存储条件汇总配置到GridView的Tag中 |
| | | var conditionSummaryConfig = new |
| | | { |
| | | ConditionField = conditionFieldName, |
| | | ConditionValue = conditionValue, |
| | | SummaryColumns = summaryColumns |
| | | }; |
| | | |
| | | // 将配置存储到GridView的Tag中(如果已有其他Tag,需要合并) |
| | | if (gridView.Tag == null) |
| | | { |
| | | gridView.Tag = conditionSummaryConfig; |
| | | } |
| | | else |
| | | { |
| | | // 如果已有Tag,创建一个复合对象 |
| | | gridView.Tag = new { Existing = gridView.Tag, ConditionSummary = conditionSummaryConfig }; |
| | | } |
| | | |
| | | // 为每个指定列设置自定义汇总计算 |
| | | foreach (var columnName in summaryColumns) |
| | | { |
| | | if (gridView.Columns[columnName] != null) |
| | | { |
| | | // 使用标准的求和汇总,但显示自定义格式 |
| | | gridView.Columns[columnName].SummaryItem.SummaryType = DevExpress.Data.SummaryItemType.Sum; |
| | | gridView.Columns[columnName].SummaryItem.DisplayFormat = "选中合计: {0}"; |
| | | } |
| | | } |
| | | |
| | | // 绑定数据变化事件,手动计算条件汇总 |
| | | gridView.CustomDrawFooterCell -= GridView_CustomDrawFooterForCondition; |
| | | gridView.CustomDrawFooterCell += GridView_CustomDrawFooterForCondition; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 自定义绘制页脚单元格,显示条件汇总结果 |
| | | /// </summary> |
| | | private static void GridView_CustomDrawFooterForCondition(object sender, DevExpress.XtraGrid.Views.Grid.FooterCellCustomDrawEventArgs e) |
| | | { |
| | | var gridView = sender as DevExpress.XtraGrid.Views.Grid.GridView; |
| | | if (gridView?.Tag == null) return; |
| | | |
| | | try |
| | | { |
| | | // 获取条件汇总配置 |
| | | dynamic config = GetConditionSummaryConfig(gridView.Tag); |
| | | if (config == null) return; |
| | | |
| | | string conditionField = config.ConditionField; |
| | | object conditionValue = config.ConditionValue; |
| | | string[] summaryColumns = config.SummaryColumns; |
| | | |
| | | // 检查当前列是否需要条件汇总 |
| | | if (summaryColumns != null && Array.IndexOf(summaryColumns, e.Column.FieldName) >= 0) |
| | | { |
| | | // 计算条件汇总值 |
| | | decimal totalValue = CalculateConditionalSum(gridView, conditionField, conditionValue, e.Column.FieldName); |
| | | |
| | | // 设置显示文本 |
| | | e.Info.DisplayText = $"{totalValue:F2}"; |
| | | |
| | | // 可以自定义显示样式 |
| | | e.Appearance.ForeColor = System.Drawing.Color.Blue; |
| | | e.Appearance.Font = new System.Drawing.Font(e.Appearance.Font, System.Drawing.FontStyle.Bold); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"条件汇总绘制错误: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取条件汇总配置 |
| | | /// </summary> |
| | | private static dynamic GetConditionSummaryConfig(object tag) |
| | | { |
| | | if (tag == null) return null; |
| | | |
| | | // 检查是否是直接的配置对象 |
| | | var tagType = tag.GetType(); |
| | | if (tagType.GetProperty("ConditionField") != null) |
| | | { |
| | | return tag; |
| | | } |
| | | |
| | | // 检查是否是复合对象 |
| | | if (tagType.GetProperty("ConditionSummary") != null) |
| | | { |
| | | dynamic composite = tag; |
| | | return composite.ConditionSummary; |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计算条件汇总值 |
| | | /// </summary> |
| | | private static decimal CalculateConditionalSum(DevExpress.XtraGrid.Views.Grid.GridView gridView, string conditionField, object conditionValue, string summaryField) |
| | | { |
| | | decimal total = 0; |
| | | |
| | | try |
| | | { |
| | | // 遍历所有可见行 |
| | | for (int i = 0; i < gridView.DataRowCount; i++) |
| | | { |
| | | // 获取条件字段值 |
| | | object conditionFieldValue = gridView.GetRowCellValue(i, conditionField); |
| | | |
| | | // 检查条件是否匹配 |
| | | if (IsConditionMatched(conditionFieldValue, conditionValue)) |
| | | { |
| | | // 获取汇总字段值 |
| | | object summaryFieldValue = gridView.GetRowCellValue(i, summaryField); |
| | | |
| | | // 累加数值 |
| | | if (summaryFieldValue != null && decimal.TryParse(summaryFieldValue.ToString(), out decimal value)) |
| | | { |
| | | total += value; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"条件汇总计算错误: {ex.Message}"); |
| | | } |
| | | |
| | | return Math.Round(total, 2); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 手动刷新条件汇总显示 - 优化版本,立即生效 |
| | | /// </summary> |
| | | public static void RefreshConditionalSummary(DevExpress.XtraGrid.Views.Grid.GridView gridView) |
| | | { |
| | | try |
| | | { |
| | | if (gridView != null) |
| | | { |
| | | // 先刷新数据绑定 |
| | | gridView.PostEditor(); |
| | | gridView.UpdateCurrentRow(); |
| | | |
| | | // 强制重绘底部汇总区域 |
| | | gridView.InvalidateFooter(); |
| | | |
| | | // 立即刷新布局 |
| | | gridView.LayoutChanged(); |
| | | |
| | | // 强制重绘整个视图 |
| | | gridView.Invalidate(); |
| | | |
| | | // 确保界面立即更新 |
| | | System.Windows.Forms.Application.DoEvents(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"刷新条件汇总错误: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 判断条件是否匹配(用于汇总) |
| | | /// </summary> |
| | | private static bool IsConditionMatched(object fieldValue, object targetValue) |
| | | { |
| | | if (fieldValue == null && targetValue == null) return true; |
| | | if (fieldValue == null || targetValue == null) return false; |
| | | |
| | | string fieldStr = fieldValue.ToString().Trim(); |
| | | string targetStr = targetValue.ToString().Trim(); |
| | | |
| | | // 处理布尔值类型的匹配 |
| | | if (IsBooleanValue(fieldStr) || IsBooleanValue(targetStr)) |
| | | { |
| | | bool fieldBool = ConvertToBoolean(fieldStr); |
| | | bool targetBool = ConvertToBoolean(targetStr); |
| | | return fieldBool == targetBool; |
| | | } |
| | | |
| | | // 处理数值类型的匹配 |
| | | if (decimal.TryParse(fieldStr, out decimal fieldNum) && decimal.TryParse(targetStr, out decimal targetNum)) |
| | | { |
| | | return fieldNum == targetNum; |
| | | } |
| | | |
| | | // 字符串匹配 |
| | | return string.Equals(fieldStr, targetStr, StringComparison.OrdinalIgnoreCase); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 检查是否为布尔值 |
| | | /// </summary> |
| | | private static bool IsBooleanValue(string value) |
| | | { |
| | | if (string.IsNullOrEmpty(value)) return false; |
| | | string lower = value.ToLower(); |
| | | return lower == "true" || lower == "false" || lower == "1" || lower == "0"; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 转换为布尔值 |
| | | /// </summary> |
| | | private static bool ConvertToBoolean(string value) |
| | | { |
| | | if (string.IsNullOrEmpty(value)) return false; |
| | | string lower = value.ToLower(); |
| | | return lower == "true" || lower == "1"; |
| | | } |
| | | #endregion |
| | | |
| | | #region 简化版GridView颜色设置方法 - 创建时间:2024年8月15日 制作人:kyy |
| | | |
| | | /// <summary> |
| | | /// 一行代码设置GridView颜色的方法 |
| | | /// 创建时间:2024年8月15日 制作人:kyy |
| | | /// 使用示例: |
| | | /// SetSimpleGridColor(gridView1, "checkStatus", "=1", "Cell", Color.Blue); |
| | | /// SetSimpleGridColor(gridView1, "jyjg", "contains合格", "Cell", Color.Green); |
| | | /// SetSimpleGridColor(gridView1, "status", "=已审核", "Row", Color.Blue); |
| | | /// SetSimpleGridColor(gridView1, "", "quantity-okRkqty>100", "Row", Color.Red); // 字段运算表达式 |
| | | /// </summary> |
| | | /// <param name="gridView">GridView控件</param> |
| | | /// <param name="fieldName">字段名(运算表达式时可为空字符串)</param> |
| | | /// <param name="condition">条件(支持: =1, contains合格, >5, >=10, 或字段运算如 fieldA+fieldB>100)</param> |
| | | /// <param name="scope">范围(Cell/单元格, Row/行, Column/列)</param> |
| | | /// <param name="color">颜色</param> |
| | | public static void SetSimpleGridColor(GridView gridView, string fieldName, string condition, string scope, Color color) |
| | | { |
| | | if (gridView == null || string.IsNullOrEmpty(condition)) |
| | | return; |
| | | |
| | | // 检查是否为运算表达式 |
| | | bool isCalculationExpression = IsCalculationExpression(condition); |
| | | |
| | | // 如果是运算表达式但没有指定fieldName,fieldName设为空 |
| | | if (isCalculationExpression && string.IsNullOrEmpty(fieldName)) |
| | | { |
| | | fieldName = ""; // 运算表达式不需要特定字段名 |
| | | } |
| | | else if (!isCalculationExpression && string.IsNullOrEmpty(fieldName)) |
| | | { |
| | | return; // 普通条件必须指定字段名 |
| | | } |
| | | |
| | | // 移除之前可能绑定的事件(避免重复绑定) |
| | | gridView.RowCellStyle -= SimpleGridColor_RowCellStyle; |
| | | |
| | | // 创建简单的颜色配置并存储到Tag |
| | | var colorConfigs = gridView.Tag as List<SimpleColorConfig> ?? new List<SimpleColorConfig>(); |
| | | |
| | | // 添加新配置 |
| | | colorConfigs.Add(new SimpleColorConfig |
| | | { |
| | | FieldName = fieldName, |
| | | Condition = condition, |
| | | Scope = scope, |
| | | Color = color |
| | | }); |
| | | |
| | | gridView.Tag = colorConfigs; |
| | | |
| | | // 绑定颜色设置事件 |
| | | gridView.RowCellStyle += SimpleGridColor_RowCellStyle; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 简单颜色配置类 |
| | | /// </summary> |
| | | private class SimpleColorConfig |
| | | { |
| | | public string FieldName { get; set; } |
| | | public string Condition { get; set; } |
| | | public string Scope { get; set; } |
| | | public Color Color { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 简化的颜色设置事件处理 |
| | | /// </summary> |
| | | private static void SimpleGridColor_RowCellStyle(object sender, RowCellStyleEventArgs e) |
| | | { |
| | | var gridView = sender as GridView; |
| | | if (gridView?.Tag is List<SimpleColorConfig> configs) |
| | | { |
| | | foreach (var config in configs) |
| | | { |
| | | // 判断是否应该应用颜色 |
| | | bool shouldApply = false; |
| | | |
| | | // 检查是否为运算表达式 |
| | | bool isCalculationExpression = IsCalculationExpression(config.Condition); |
| | | |
| | | if (isCalculationExpression) |
| | | { |
| | | // 运算表达式根据范围决定是否应用 |
| | | if (config.Scope.ToLower() == "row") |
| | | shouldApply = true; // 整行应用 |
| | | else if (config.Scope.ToLower() == "cell") |
| | | shouldApply = true; // 所有单元格都尝试应用 |
| | | else if (config.Scope.ToLower() == "column") |
| | | shouldApply = true; // 所有列都尝试应用 |
| | | } |
| | | else |
| | | { |
| | | // 普通字段条件 |
| | | if (config.Scope.ToLower() == "cell" && e.Column.FieldName == config.FieldName) |
| | | shouldApply = true; |
| | | else if (config.Scope.ToLower() == "row") |
| | | shouldApply = true; |
| | | else if (config.Scope.ToLower() == "column" && e.Column.FieldName == config.FieldName) |
| | | shouldApply = true; |
| | | } |
| | | |
| | | if (!shouldApply) continue; |
| | | |
| | | bool conditionMatched = false; |
| | | |
| | | if (isCalculationExpression) |
| | | { |
| | | // 处理字段运算表达式 |
| | | try |
| | | { |
| | | decimal result = EvaluateExpression(gridView, e.RowHandle, config.Condition); |
| | | conditionMatched = result == 1; // 1表示条件满足,0表示不满足 |
| | | |
| | | if (conditionMatched) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"运算表达式匹配成功 - 表达式: {config.Condition}, 行: {e.RowHandle}"); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"运算表达式计算失败 - 表达式: {config.Condition}, 错误: {ex.Message}"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // 处理单字段条件 |
| | | object cellValue = gridView.GetRowCellValue(e.RowHandle, config.FieldName); |
| | | if (cellValue != null) |
| | | { |
| | | string stringValue = cellValue.ToString().Trim(); |
| | | |
| | | // 调试信息:输出实际的字段值 |
| | | if (config.FieldName == "checkStatus" && e.RowHandle < 3) // 只输出前几行避免太多日志 |
| | | { |
| | | System.Diagnostics.Debug.WriteLine($"字段值调试 - 字段: {config.FieldName}, 实际值: '{stringValue}', 类型: {cellValue.GetType().Name}, 条件: {config.Condition}"); |
| | | } |
| | | |
| | | // 判断条件是否匹配 |
| | | conditionMatched = IsConditionMatch(stringValue, config.Condition); |
| | | } |
| | | } |
| | | |
| | | if (conditionMatched) |
| | | { |
| | | e.Appearance.ForeColor = config.Color; |
| | | System.Diagnostics.Debug.WriteLine($"颜色匹配成功 - 字段/表达式: {config.FieldName ?? config.Condition}, 条件: {config.Condition}"); |
| | | break; // 匹配到第一个条件就停止 |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 检查是否为计算表达式(包含字段运算) |
| | | /// </summary> |
| | | private static bool IsCalculationExpression(string condition) |
| | | { |
| | | if (string.IsNullOrEmpty(condition)) |
| | | return false; |
| | | |
| | | // 检查是否包含数学运算符和比较运算符的组合 |
| | | char[] mathOperators = { '+', '-', '*', '/' }; |
| | | string[] comparisonOperators = { ">=", "<=", ">", "<", "=", "!=" }; |
| | | |
| | | bool hasMathOperator = condition.IndexOfAny(mathOperators) >= 0; |
| | | bool hasComparisonOperator = comparisonOperators.Any(op => condition.Contains(op)); |
| | | |
| | | // 如果同时包含数学运算符和比较运算符,就认为是计算表达式 |
| | | return hasMathOperator && hasComparisonOperator; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 判断条件是否匹配 |
| | | /// </summary> |
| | | private static bool IsConditionMatch(string value, string condition) |
| | | { |
| | | if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(condition)) |
| | | return false; |
| | | |
| | | condition = condition.Trim(); |
| | | value = value.Trim(); |
| | | |
| | | // 处理contains条件 |
| | | if (condition.StartsWith("contains", StringComparison.OrdinalIgnoreCase)) |
| | | { |
| | | string matchText = condition.Substring(8).Trim(); |
| | | |
| | | // 移除前缀处理(如"M:免检"中的"M:") |
| | | string processedValue = value; |
| | | int colonIndex = processedValue.IndexOf(':'); |
| | | if (colonIndex >= 0 && colonIndex < processedValue.Length - 1) |
| | | { |
| | | processedValue = processedValue.Substring(colonIndex + 1).Trim(); |
| | | } |
| | | |
| | | return processedValue.IndexOf(matchText, StringComparison.OrdinalIgnoreCase) >= 0; |
| | | } |
| | | |
| | | // 处理等于条件 |
| | | if (condition.StartsWith("=")) |
| | | { |
| | | string targetValue = condition.Substring(1).Trim(); |
| | | |
| | | // 特殊处理bit类型字段(Boolean值) |
| | | if (IsBooleanCondition(targetValue)) |
| | | { |
| | | return IsBooleanMatch(value, targetValue); |
| | | } |
| | | |
| | | return string.Equals(value, targetValue, StringComparison.OrdinalIgnoreCase); |
| | | } |
| | | |
| | | // 处理数值比较条件 |
| | | if (decimal.TryParse(value, out decimal numericValue)) |
| | | { |
| | | if (condition.StartsWith(">=")) |
| | | { |
| | | if (decimal.TryParse(condition.Substring(2).Trim(), out decimal target)) |
| | | return numericValue >= target; |
| | | } |
| | | else if (condition.StartsWith("<=")) |
| | | { |
| | | if (decimal.TryParse(condition.Substring(2).Trim(), out decimal target)) |
| | | return numericValue <= target; |
| | | } |
| | | else if (condition.StartsWith(">")) |
| | | { |
| | | if (decimal.TryParse(condition.Substring(1).Trim(), out decimal target)) |
| | | return numericValue > target; |
| | | } |
| | | else if (condition.StartsWith("<")) |
| | | { |
| | | if (decimal.TryParse(condition.Substring(1).Trim(), out decimal target)) |
| | | return numericValue < target; |
| | | } |
| | | else if (decimal.TryParse(condition, out decimal target)) |
| | | { |
| | | return numericValue == target; |
| | | } |
| | | } |
| | | |
| | | // 检查是否是布尔值条件 |
| | | if (IsBooleanCondition(condition)) |
| | | { |
| | | return IsBooleanMatch(value, condition); |
| | | } |
| | | |
| | | // 默认按字符串相等处理 |
| | | return string.Equals(value, condition, StringComparison.OrdinalIgnoreCase); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 判断多字段运算条件是否匹配(支持字段间运算) |
| | | /// </summary> |
| | | private static bool IsConditionMatchWithCalculation(GridView gridView, int rowHandle, string condition) |
| | | { |
| | | if (string.IsNullOrEmpty(condition)) |
| | | return false; |
| | | |
| | | condition = condition.Trim(); |
| | | |
| | | try |
| | | { |
| | | // 解析并计算表达式 |
| | | decimal calculatedValue = EvaluateExpression(gridView, rowHandle, condition); |
| | | |
| | | // 如果表达式计算成功,返回true(表示条件满足) |
| | | return true; |
| | | } |
| | | catch |
| | | { |
| | | // 如果计算失败,返回false |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计算包含字段名的表达式 |
| | | /// 支持格式:fieldA+fieldB>100, fieldA-fieldB<=50, fieldA*fieldB>=fieldC等 |
| | | /// </summary> |
| | | private static decimal EvaluateExpression(GridView gridView, int rowHandle, string expression) |
| | | { |
| | | // 提取比较运算符和目标值 |
| | | string[] operators = { ">=", "<=", ">", "<", "=", "!=" }; |
| | | string op = ""; |
| | | string leftExpression = ""; |
| | | string rightExpression = ""; |
| | | |
| | | foreach (var oper in operators) |
| | | { |
| | | if (expression.Contains(oper)) |
| | | { |
| | | string[] parts = expression.Split(new string[] { oper }, StringSplitOptions.None); |
| | | if (parts.Length == 2) |
| | | { |
| | | op = oper; |
| | | leftExpression = parts[0].Trim(); |
| | | rightExpression = parts[1].Trim(); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (string.IsNullOrEmpty(op)) |
| | | throw new ArgumentException("无效的表达式格式"); |
| | | |
| | | // 计算左侧表达式的值 |
| | | decimal leftValue = CalculateFieldExpression(gridView, rowHandle, leftExpression); |
| | | |
| | | // 计算右侧表达式的值(可能是数字或字段表达式) |
| | | decimal rightValue; |
| | | if (decimal.TryParse(rightExpression, out rightValue)) |
| | | { |
| | | // 右侧是数字 |
| | | } |
| | | else |
| | | { |
| | | // 右侧是字段表达式 |
| | | rightValue = CalculateFieldExpression(gridView, rowHandle, rightExpression); |
| | | } |
| | | |
| | | // 根据运算符判断条件是否满足 |
| | | switch (op) |
| | | { |
| | | case ">=": |
| | | return leftValue >= rightValue ? 1 : 0; |
| | | case "<=": |
| | | return leftValue <= rightValue ? 1 : 0; |
| | | case ">": |
| | | return leftValue > rightValue ? 1 : 0; |
| | | case "<": |
| | | return leftValue < rightValue ? 1 : 0; |
| | | case "=": |
| | | return leftValue == rightValue ? 1 : 0; |
| | | case "!=": |
| | | return leftValue != rightValue ? 1 : 0; |
| | | default: |
| | | throw new ArgumentException($"不支持的运算符: {op}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计算包含字段运算的表达式(如:fieldA+fieldB-fieldC*2) |
| | | /// </summary> |
| | | private static decimal CalculateFieldExpression(GridView gridView, int rowHandle, string expression) |
| | | { |
| | | expression = expression.Trim(); |
| | | |
| | | // 简单的表达式解析器 - 按运算优先级处理 |
| | | // 先处理乘除,再处理加减 |
| | | |
| | | // 分割加减运算 |
| | | var addSubTerms = SplitExpression(expression, new[] { '+', '-' }); |
| | | decimal result = 0; |
| | | char lastOp = '+'; |
| | | |
| | | foreach (var term in addSubTerms) |
| | | { |
| | | string cleanTerm = term.Key.Trim(); |
| | | char op = term.Value; |
| | | |
| | | // 处理乘除运算 |
| | | decimal termValue = CalculateMultiplyDivide(gridView, rowHandle, cleanTerm); |
| | | |
| | | if (lastOp == '+') |
| | | result += termValue; |
| | | else if (lastOp == '-') |
| | | result -= termValue; |
| | | |
| | | lastOp = op; |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理乘除运算 |
| | | /// </summary> |
| | | private static decimal CalculateMultiplyDivide(GridView gridView, int rowHandle, string expression) |
| | | { |
| | | var mulDivTerms = SplitExpression(expression, new[] { '*', '/' }); |
| | | decimal result = 0; |
| | | char lastOp = '*'; |
| | | bool isFirst = true; |
| | | |
| | | foreach (var term in mulDivTerms) |
| | | { |
| | | string cleanTerm = term.Key.Trim(); |
| | | char op = term.Value; |
| | | |
| | | decimal termValue = GetFieldOrNumericValue(gridView, rowHandle, cleanTerm); |
| | | |
| | | if (isFirst) |
| | | { |
| | | result = termValue; |
| | | isFirst = false; |
| | | } |
| | | else if (lastOp == '*') |
| | | result *= termValue; |
| | | else if (lastOp == '/') |
| | | result /= termValue; |
| | | |
| | | lastOp = op; |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 分割表达式 |
| | | /// </summary> |
| | | private static List<KeyValuePair<string, char>> SplitExpression(string expression, char[] operators) |
| | | { |
| | | var result = new List<KeyValuePair<string, char>>(); |
| | | string currentTerm = ""; |
| | | |
| | | for (int i = 0; i < expression.Length; i++) |
| | | { |
| | | char c = expression[i]; |
| | | |
| | | if (operators.Contains(c)) |
| | | { |
| | | if (!string.IsNullOrEmpty(currentTerm)) |
| | | { |
| | | result.Add(new KeyValuePair<string, char>(currentTerm, i < expression.Length - 1 ? c : '\0')); |
| | | currentTerm = ""; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | currentTerm += c; |
| | | } |
| | | } |
| | | |
| | | if (!string.IsNullOrEmpty(currentTerm)) |
| | | { |
| | | result.Add(new KeyValuePair<string, char>(currentTerm, '\0')); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取字段值或数值 |
| | | /// </summary> |
| | | private static decimal GetFieldOrNumericValue(GridView gridView, int rowHandle, string valueExpression) |
| | | { |
| | | valueExpression = valueExpression.Trim(); |
| | | |
| | | // 尝试解析为数字 |
| | | if (decimal.TryParse(valueExpression, out decimal numValue)) |
| | | { |
| | | return numValue; |
| | | } |
| | | |
| | | // 作为字段名处理 |
| | | try |
| | | { |
| | | object cellValue = gridView.GetRowCellValue(rowHandle, valueExpression); |
| | | if (cellValue != null && decimal.TryParse(cellValue.ToString(), out decimal fieldValue)) |
| | | { |
| | | return fieldValue; |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | // 字段不存在或无法转换为数字 |
| | | } |
| | | |
| | | return 0; // 默认值 |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 检查是否是布尔值条件 |
| | | /// </summary> |
| | | private static bool IsBooleanCondition(string condition) |
| | | { |
| | | string lowerCondition = condition.ToLower(); |
| | | return lowerCondition == "true" || lowerCondition == "false" || |
| | | lowerCondition == "1" || lowerCondition == "0"; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 布尔值匹配检查 |
| | | /// </summary> |
| | | private static bool IsBooleanMatch(string value, string condition) |
| | | { |
| | | // 标准化布尔值 |
| | | bool conditionBool = NormalizeBooleanValue(condition); |
| | | bool valueBool = NormalizeBooleanValue(value); |
| | | |
| | | return conditionBool == valueBool; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 标准化布尔值 |
| | | /// </summary> |
| | | private static bool NormalizeBooleanValue(string value) |
| | | { |
| | | if (string.IsNullOrEmpty(value)) |
| | | return false; |
| | | |
| | | string lowerValue = value.Trim().ToLower(); |
| | | |
| | | // 处理各种可能的true值 |
| | | if (lowerValue == "true" || lowerValue == "1" || lowerValue == "是" || lowerValue == "已审核") |
| | | return true; |
| | | |
| | | // 处理各种可能的false值 |
| | | if (lowerValue == "false" || lowerValue == "0" || lowerValue == "否" || lowerValue == "未审核" || lowerValue == "") |
| | | return false; |
| | | |
| | | // 默认为false |
| | | return false; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 设置GridView复选框列点击时自动刷新条件汇总 |
| | | /// 2025-08-15 kyy 新增公用方法 |
| | | /// </summary> |
| | | /// <param name="gridView">目标GridView控件</param> |
| | | /// <param name="checkboxFieldName">复选框字段名(默认为chkInt)</param> |
| | | /// <param name="delayMs">延迟刷新时间(毫秒,默认100ms)</param> |
| | | public static void SetupCheckboxClickRefresh(DevExpress.XtraGrid.Views.Grid.GridView gridView, string checkboxFieldName = "chkInt", int delayMs = 100) |
| | | { |
| | | if (gridView == null) return; |
| | | |
| | | // 添加鼠标点击事件,检测复选框列点击 |
| | | gridView.MouseDown += (s, e) => |
| | | { |
| | | var hitInfo = gridView.CalcHitInfo(e.Location); |
| | | if (hitInfo.InRowCell && hitInfo.Column?.FieldName == checkboxFieldName) |
| | | { |
| | | // 复选框列被点击,延迟刷新汇总确保值已更新 |
| | | System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); |
| | | timer.Interval = delayMs; |
| | | timer.Tick += (sender, args) => |
| | | { |
| | | timer.Stop(); |
| | | timer.Dispose(); |
| | | RefreshConditionalSummary(gridView); |
| | | }; |
| | | timer.Start(); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 一键设置GridView条件汇总的完整功能(包含条件汇总+实时刷新) |
| | | /// 2025-08-15 kyy 新增便捷方法 |
| | | /// </summary> |
| | | /// <param name="gridView">目标GridView控件</param> |
| | | /// <param name="conditionFieldName">条件字段名(如chkInt)</param> |
| | | /// <param name="conditionValue">条件值(如true表示选中)</param> |
| | | /// <param name="summaryColumns">需要汇总的列名数组</param> |
| | | /// <param name="enableRealTimeRefresh">是否启用实时刷新(默认true)</param> |
| | | /// <param name="refreshDelayMs">刷新延迟时间(毫秒,默认100ms)</param> |
| | | public static void SetupCompleteConditionalSummary(DevExpress.XtraGrid.Views.Grid.GridView gridView, |
| | | string conditionFieldName, object conditionValue, string[] summaryColumns, |
| | | bool enableRealTimeRefresh = true, int refreshDelayMs = 100) |
| | | { |
| | | if (gridView == null || summaryColumns == null || summaryColumns.Length == 0) return; |
| | | |
| | | // 1. 设置条件汇总 |
| | | SetupGridSummaryWithCondition(gridView, conditionFieldName, conditionValue, summaryColumns); |
| | | |
| | | if (!enableRealTimeRefresh) return; |
| | | |
| | | // 2. 设置实时刷新事件 |
| | | // 单元格值变化事件 |
| | | gridView.CellValueChanged += (s, e) => |
| | | { |
| | | if (e.Column.FieldName == conditionFieldName) |
| | | { |
| | | RefreshConditionalSummary(gridView); |
| | | } |
| | | }; |
| | | |
| | | // 数据源变化事件 |
| | | gridView.DataSourceChanged += (s, e) => |
| | | { |
| | | RefreshConditionalSummary(gridView); |
| | | }; |
| | | |
| | | // 编辑器隐藏事件 |
| | | gridView.HiddenEditor += (s, e) => |
| | | { |
| | | System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); |
| | | timer.Interval = 50; |
| | | timer.Tick += (sender, args) => |
| | | { |
| | | timer.Stop(); |
| | | timer.Dispose(); |
| | | RefreshConditionalSummary(gridView); |
| | | }; |
| | | timer.Start(); |
| | | }; |
| | | |
| | | // 3. 设置复选框点击刷新 |
| | | SetupCheckboxClickRefresh(gridView, conditionFieldName, refreshDelayMs); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | } |
| | | |
| | |
| | | return Text.ToString(); |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | /// <summary> |