Datatable.Compute小技巧

        在个人版机房重构的过程中,大家最发愁的一件事无非就是上下机,结账和报表。那么在结账的过程中,最发愁的是否就数计算日结账单的数据和周结账的数据。还记得在第一遍机房收费系统的过程中用的是for 循环,但是现在考虑多了为了节省时间能不能不用那么长的循环直接用某个函数求和?所以带着这个问题,就进入了查找资料的过程。得知在Datatable中可以直接求出某行某列的和,所以这就是Datatable.Compute小技巧的由来。

        那么接下来就进入DataTable.Compute的学习吧!

以前你肯定没想到DataTable.Compute具有这么多的功能

1:聚合函数”Sum()

2:自由计算表达式“20*30+1

3bool表达式“1=2

4IFF逻辑表达式” IIF(20>1000, 0, 1)” //还支持IsNullTrimSubString

一个小应用:让DataTable模拟ExcelFormula功能。

Excel中的Formula功能强大,如果能让DataTable有类似的功能就好了。大部分事件DataTable只是用作数据载体,其实很少用它做计算。DataTable提供的函数Compute就提供了功能强大的计算功能。

Compute函数的参数就两个:Expression,和Filter

Expresstion是计算表达式,

Filter则是条件过滤器,类似sqlWhere条件。

1: 这里详细介绍的就是Expresstion

      1)先看最简单的用法,使用聚合函数。这个聚合函数就是报表或者Excel中常用的函数,比如SumAvg等等。对于数据列,Datatable可以方便的进行计算,比如DataTable.Cumpute(Sum(1),”列1>0”); 对于简单的统计功能,这些函数就足够用了。(其他提供的函数有minmaxcount,求方差,标准偏差等等)。这个功能常用,倒也不奇怪。

      2)再看“自由表达式”计算。把数学计算表达式写成字符串,然后直接投入Compute函数计算,就可以得到计算结果。这样,动态生成的计算表达式就可以计算出来了。比方说要计算“列1×30+20+2”或者是纯粹的数学计算。

      3)除了计算出具体的结果,Compute函数还能进行逻辑计算。比方说这个表达式就能返回falseCompute(1=2,true); 这个的用法可能想上边的情形差不多,在自由组装一些条件的时候可以得到结果。

      4)最后Excel中,还经常用到的就是LogicTest功能了,可以指定一些逻辑表达式,比如这样的:“IF(20>1000, 0, 1)”。而这个功能要是放到DataTable中该如何实现呢?也是用Compute,这样写就可以了:“IIF(20>1000,0, 1)”。在DataTable里面如果实现“IF(C102=0,0,C105/C102*30)”就用上边的这些技术点就可以了。

2:第二个参数Filter,就是一个简单的查询条件。比如,”true, Id>4”, “Name like ’%nd’ andsex=’male’”.条件不可能很复杂,这些已经比较够用了。

以前用过的Marge什么的也不错,还可以作内连接,在数据量小,需要简单计算的情况下,这些功能很有用。

当然,如果逻辑极其复杂,DT的这点功能就不够了,还是得自己写逻辑(即使要实现“IF(C102=0,0,C105/C102*30)”,也是要自己写一点处理逻辑的,不过比较通用,写一次就好了)。

3注意点,通过以上的讲解,是否对Datatable.Compute有了一定的了解,但是真的会运用了吗?接下来就进入我们的大拷问吧!

       大家看一下表达式是否合法:

Sum (Quantity *UnitPrice)

       答案是:No

       如果必须针对两列或多列执行操作,则应该创建 DataColumn,并将它的 Expression属性设置为适当的表达式,然后针对结果列使用聚合表达式。在这种情况下,假定有一个名为“total”的 DataColumn,并且 Expression属性设置为:"Quantity * UnitPrice"

Compute 方法的表达式参数将为:Sum(total)

       综上所述就是我对Datatable.Compute小技巧的理解,希望给大家带来方便!在今后的学习中会不断地完善,加油!

using System; using System.Data; using System.Data.OleDb; using System.IO; using System.Collections.Generic; using System.Reflection; using System.Security.Cryptography; using System.Text; using NXOpen; using NXOpen.CAM; using NXOpen.UF; using System.Linq; using System.Diagnostics; using System.CodeDom.Compiler; using Microsoft.CSharp; using Path = System.IO.Path; namespace NXCamAutomation { public static class DataReaderExtensions { public static string GetValueSafe(this OleDbDataReader reader, int colIndex) { return reader.FieldCount > colIndex && !reader.IsDBNull(colIndex) ? reader.GetValue(colIndex)?.ToString()?.Trim() ?? "" : ""; } } public static class AppConfig { public static string AppDir => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); public static string KeyFetcherExePath => Path.Combine(AppDir, "KeyFetcher_Cache.exe"); public static string TempKeyPath => Path.Combine(AppDir, "temp_sk.tmp"); public static string KeyDllPath => Path.Combine(AppDir, "MiYao_Helper.dll"); public static string ExcelConfigPath => Path.Combine(AppDir, @"..\Excel\工序配置表.xlsx"); public const int CacheDurationMinutes = 720; public const int KeyFetchTimeoutMs = 2000; public const int ExcelReadMaxRows = 500; public static class Excel { public const int OpRow = 3, OpCol = 1; public const int ToolRow = 3, ToolCol = 2; public const int MethodRow = 3, MethodCol = 3; public const int TemplateRow = 3, TemplateCol = 4; public const int ProgramRow = 3, ProgramCol = 9; public const int GeomRow = 3, GeomCol = 10; public const string Sql = "SELECT * FROM [{0}]"; } public static readonly byte[] EncryptKey = Encoding.UTF8.GetBytes("8Zx2P7q9Ym3Rf5Tk"); public static readonly byte[] EncryptIv = Encoding.UTF8.GetBytes("4Dv6Gs8Hj0Kl2Np1"); } public class NXMainProgram { private static Session _theSession; private static UFSession _ufSession; private static Dictionary<string, NCGroup> _cachedCamGroupsDict; private static string[] _cachedExcelData; private static DateTime _excelCacheTimestamp; private static string _cachedHardwareId; private static string _cachedExcelHash; static NXMainProgram() { try { _cachedHardwareId = GetLocalHardwareId(); if (File.Exists(AppConfig.ExcelConfigPath)) { _cachedExcelHash = ComputeFileHash(AppConfig.ExcelConfigPath); // 修复:添加ComputeFileHash方法调用 _cachedExcelData = ReadExcelConfig(); // 修复:添加ReadExcelConfig方法调用 _excelCacheTimestamp = DateTime.Now; } using (var dummyConn = new OleDbConnection()) { } if (!File.Exists(AppConfig.KeyFetcherExePath)) { System.Diagnostics.Debug.WriteLine("KeyFetcher_Cache.exe未找到,后续将自动编译"); } } catch { } } public static void Main(string[] args) { if (!InitNXSession()) return; try { if (!File.Exists(AppConfig.KeyDllPath)) { ShowErrorDialog("主程序目录缺少“密钥.dll”!请手动补充后重试"); return; } CleanExpiredOrMismatchedCache(); bool filesCompleted = AutoCompleteMissingFiles(); if (!ValidateSecuritySystem()) { ShowNetworkErrorDialog(); return; } var workPart = _theSession.Parts.Work; if (workPart == null) { ShowErrorDialog("无当前工作部件!"); return; } ExecuteMainLogic(workPart); // 修复:添加ExecuteMainLogic方法调用 } catch (Exception ex) { ShowErrorDialog($"程序执行失败:{ex.Message}"); } } private static bool AutoCompleteMissingFiles() { bool exeExists = File.Exists(AppConfig.KeyFetcherExePath); bool cacheExists = File.Exists(AppConfig.TempKeyPath); bool completed = true; if (!exeExists) { completed = CompileFetcherExe(); if (!completed) { ShowErrorDialog("编译KeyFetcher_Cache.exe失败,请检查目录写入权限"); return false; } } if (completed && !cacheExists) { string key = CallKeyFetcher(); if (string.IsNullOrEmpty(key)) { return false; } string encryptedKey = EncryptString(key); completed = SafeWriteFile(AppConfig.TempKeyPath, encryptedKey); } return completed; } private static bool CompileFetcherExe() { try { string fetcherCode = $@" using System; using System.Reflection; using System.IO; class KeyFetcher {{ static void Main(string[] args) {{ try {{ if (args.Length == 0) return; string keyDllPath = args[0]; if (!File.Exists(keyDllPath)) return; Assembly securityAssembly = Assembly.LoadFile(keyDllPath); Type managerType = securityAssembly.GetType(""SecurityKeyManager""); if (managerType == null) return; MethodInfo getKeyMethod = managerType.GetMethod(""GetSecurityKey"", BindingFlags.Public | BindingFlags.Static); if (getKeyMethod == null) return; string key = getKeyMethod.Invoke(null, null) as string; Console.WriteLine(key); }} catch {{}} }} }}"; using (var provider = new CSharpCodeProvider()) { var parameters = new CompilerParameters { OutputAssembly = AppConfig.KeyFetcherExePath, GenerateExecutable = true, ReferencedAssemblies = { "System.dll", "System.IO.dll", "System.Reflection.dll" }, CompilerOptions = "/optimize+" }; CompilerResults results = provider.CompileAssemblyFromSource(parameters, fetcherCode); return !results.Errors.HasErrors; } } catch { return false; } } private static string CallKeyFetcher() { using (var fetcher = new Process()) { fetcher.StartInfo = new ProcessStartInfo { FileName = AppConfig.KeyFetcherExePath, Arguments = $"\"{AppConfig.KeyDllPath}\"", WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true, LoadUserProfile = false }; try { fetcher.Start(); bool completed = fetcher.WaitForExit(AppConfig.KeyFetchTimeoutMs); if (!completed) { fetcher.Kill(); return null; } return fetcher.StandardOutput.ReadToEnd().Trim(); } catch { return null; } } } private static void CleanExpiredOrMismatchedCache() { if (!File.Exists(AppConfig.TempKeyPath)) return; bool needClean = false; try { FileInfo tempFile = new FileInfo(AppConfig.TempKeyPath); if (DateTime.Now - tempFile.CreationTime > TimeSpan.FromMinutes(AppConfig.CacheDurationMinutes)) { needClean = true; } else { string decryptedKey = DecryptString(SafeReadFile(AppConfig.TempKeyPath)); if (string.IsNullOrEmpty(decryptedKey)) { needClean = true; } } } catch { needClean = true; } if (needClean) { CleanCacheFiles(); } } private static void CleanCacheFiles() { SafeDeleteFile(AppConfig.TempKeyPath); SafeDeleteFile(AppConfig.KeyFetcherExePath); } private static bool InitNXSession() { try { _theSession = Session.GetSession(); _ufSession = UFSession.GetUFSession(); return _theSession != null && _ufSession != null; } catch { return false; } } private static bool ValidateSecuritySystem() { if (CheckCachedKeyValid()) { return true; } return FetchAndStoreNewKey(); } private static bool CheckCachedKeyValid() { if (!File.Exists(AppConfig.TempKeyPath)) return false; try { string decryptedKey = DecryptString(SafeReadFile(AppConfig.TempKeyPath)); return !string.IsNullOrEmpty(decryptedKey); } catch { CleanCacheFiles(); return false; } } private static bool FetchAndStoreNewKey() { string key = CallKeyFetcher(); if (string.IsNullOrEmpty(key)) { CleanCacheFiles(); return false; } string encryptedKey = EncryptString(key); if (!SafeWriteFile(AppConfig.TempKeyPath, encryptedKey)) { return false; } return true; } private static void ShowNetworkErrorDialog() { try { _ufSession.Ui.LockUgAccess(1); _ufSession.Ui.DisplayMessage( "未检测到小鲁班加密锁!\n\n请检查:\n1. 网络是否正常连接\n2. 加密锁是否已插入\n3. 云授权/软锁是否已登录", 1 ); } finally { _ufSession.Ui.UnlockUgAccess(1); } } private static void ShowErrorDialog(string msg) { try { _ufSession.Ui.LockUgAccess(1); _ufSession.Ui.DisplayMessage(msg, 1); } finally { _ufSession.Ui.UnlockUgAccess(1); } } private static string GetLocalHardwareId() { if (!string.IsNullOrEmpty(_cachedHardwareId)) { return _cachedHardwareId; } try { string systemDriveRoot = Path.GetPathRoot(Environment.SystemDirectory); if (string.IsNullOrEmpty(systemDriveRoot)) return null; DriveInfo systemDrive = new DriveInfo(systemDriveRoot); if (!systemDrive.IsReady) return null; string driveSerial = GetDriveSerialNumber(systemDriveRoot); string driveVolume = systemDrive.VolumeLabel.Trim(); using (MD5 md5 = MD5.Create()) { byte[] bytes = Encoding.UTF8.GetBytes(driveSerial + driveVolume); _cachedHardwareId = BitConverter.ToString(md5.ComputeHash(bytes)).Replace("-", "").ToLower(); return _cachedHardwareId; } } catch (Exception ex) { ShowErrorDialog($"获取硬件ID失败:{ex.Message}"); return null; } } private static string SafeReadFile(string path) { if (!File.Exists(path)) return null; try { using (var reader = new StreamReader(path, Encoding.UTF8, false, 8192)) { return reader.ReadToEnd(); } } catch (Exception ex) { ShowErrorDialog($"读取文件失败:{path}\n{ex.Message}"); return null; } } private static bool SafeWriteFile(string path, string content) { try { string dir = Path.GetDirectoryName(path); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); string tempPath = path + ".tmp"; using (var writer = new StreamWriter(tempPath, false, Encoding.UTF8, 8192)) { writer.Write(content); } if (File.Exists(path)) File.Delete(path); File.Move(tempPath, path); return true; } catch (Exception ex) { ShowErrorDialog($"写入文件失败:{path}\n{ex.Message}"); return false; } } private static void SafeDeleteFile(string path) { if (!File.Exists(path)) return; try { File.Delete(path); } catch (Exception ex) { ShowErrorDialog($"删除文件失败:{path}\n{ex.Message}"); } } [System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)] private static extern bool GetVolumeInformation(string lpRootPathName, StringBuilder lpVolumeNameBuffer, uint nVolumeNameSize, ref uint lpVolumeSerialNumber, ref uint lpMaximumComponentLength, ref uint lpFileSystemFlags, StringBuilder lpFileSystemNameBuffer, uint nFileSystemNameSize); private static string GetDriveSerialNumber(string drivePath) { uint serial = 0; uint maxComponentLength = 0; uint fileSystemFlags = 0; StringBuilder volumeName = new StringBuilder(256); StringBuilder fileSystemName = new StringBuilder(256); GetVolumeInformation(drivePath, volumeName, (uint)volumeName.Capacity, ref serial, ref maxComponentLength, ref fileSystemFlags, fileSystemName, (uint)fileSystemName.Capacity); return serial.ToString("X8"); } private static string EncryptString(string plainText) { try { string hardwareId = GetLocalHardwareId(); if (string.IsNullOrEmpty(hardwareId)) return null; plainText += "|" + hardwareId; using (Aes aesAlg = Aes.Create()) { aesAlg.Key = AppConfig.EncryptKey; aesAlg.IV = AppConfig.EncryptIv; aesAlg.Mode = CipherMode.CBC; aesAlg.Padding = PaddingMode.PKCS7; using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, aesAlg.CreateEncryptor(), CryptoStreamMode.Write)) using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(plainText); } return Convert.ToBase64String(msEncrypt.ToArray()); } } } catch (Exception ex) { ShowErrorDialog($"加密失败:{ex.Message}"); return null; } } private static string DecryptString(string cipherText) { try { using (Aes aesAlg = Aes.Create()) { aesAlg.Key = AppConfig.EncryptKey; aesAlg.IV = AppConfig.EncryptIv; aesAlg.Mode = CipherMode.CBC; aesAlg.Padding = PaddingMode.PKCS7; byte[] cipherBytes = Convert.FromBase64String(cipherText); using (MemoryStream msDecrypt = new MemoryStream(cipherBytes)) using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesAlg.CreateDecryptor(), CryptoStreamMode.Read)) using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { string[] parts = srDecrypt.ReadToEnd().Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); return parts.Length == 2 && parts[1] == GetLocalHardwareId() ? parts[0] : null; } } } catch (Exception ex) { ShowErrorDialog($"解密失败:{ex.Message}"); return null; // 修复:确保所有代码路径返回值 } } // 修复:添加ExecuteMainLogic方法完整实现 private static void ExecuteMainLogic(Part workPart) { var markId1 = _theSession.SetUndoMark(Session.MarkVisibility.Visible, "创建工序"); try { var excelData = ReadExcelConfig(); if (excelData == null) return; CacheCamGroups(workPart); var camGroups = FindCamGroupsByConfig(excelData); if (camGroups == null) return; var operation = workPart.CAMSetup.CAMOperationCollection.Create( camGroups[0], camGroups[1], camGroups[2], camGroups[3], excelData[3], excelData[0], NXOpen.CAM.OperationCollection.UseDefaultName.True, "FLOOR_FACING01" ); if (operation == null) return; OpenOperationDialog(operation); } catch (Exception ex) { ShowErrorDialog(ex.Message); } } private static void CacheCamGroups(Part workPart) { _cachedCamGroupsDict = new Dictionary<string, NCGroup>(StringComparer.OrdinalIgnoreCase); foreach (NCGroup camGroup in workPart.CAMSetup.CAMGroupCollection) { if (!_cachedCamGroupsDict.ContainsKey(camGroup.Name)) { _cachedCamGroupsDict.Add(camGroup.Name, camGroup); } } } // 修复:添加ReadExcelConfig方法完整实现 private static string[] ReadExcelConfig() { if (!File.Exists(AppConfig.ExcelConfigPath)) { ShowErrorDialog("未找到Excel配置文件:" + AppConfig.ExcelConfigPath); return null; } string currentHash = ComputeFileHash(AppConfig.ExcelConfigPath); var fileInfo = new FileInfo(AppConfig.ExcelConfigPath); if (_cachedExcelData != null && currentHash == _cachedExcelHash && fileInfo.LastWriteTime <= _excelCacheTimestamp && DateTime.Now - _excelCacheTimestamp <= TimeSpan.FromMinutes(AppConfig.CacheDurationMinutes)) { return _cachedExcelData; } try { var connStr = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={AppConfig.ExcelConfigPath};Extended Properties=\"Excel 12.0;HDR=NO\""; var result = new string[6]; int foundCount = 0; using (var conn = new OleDbConnection(connStr)) { conn.Open(); var schema = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); if (schema.Rows.Count == 0) return null; var tableName = schema.Rows[0]["TABLE_NAME"].ToString(); using (var cmd = new OleDbCommand(string.Format(AppConfig.Excel.Sql, tableName), conn)) using (var reader = cmd.ExecuteReader()) { int rowCount = 0; while (reader.Read() && foundCount < 6 && rowCount < AppConfig.ExcelReadMaxRows) { rowCount++; if (rowCount == AppConfig.Excel.OpRow && string.IsNullOrEmpty(result[0])) { result[0] = reader.GetValueSafe(AppConfig.Excel.OpCol - 1); foundCount++; } if (rowCount == AppConfig.Excel.ToolRow && string.IsNullOrEmpty(result[1])) { result[1] = reader.GetValueSafe(AppConfig.Excel.ToolCol - 1); foundCount++; } if (rowCount == AppConfig.Excel.MethodRow && string.IsNullOrEmpty(result[2])) { result[2] = reader.GetValueSafe(AppConfig.Excel.MethodCol - 1); foundCount++; } if (rowCount == AppConfig.Excel.TemplateRow && string.IsNullOrEmpty(result[3])) { result[3] = reader.GetValueSafe(AppConfig.Excel.TemplateCol - 1); foundCount++; } if (rowCount == AppConfig.Excel.ProgramRow && string.IsNullOrEmpty(result[4])) { result[4] = reader.GetValueSafe(AppConfig.Excel.ProgramCol - 1); foundCount++; } if (rowCount == AppConfig.Excel.GeomRow && string.IsNullOrEmpty(result[5])) { result[5] = reader.GetValueSafe(AppConfig.Excel.GeomCol - 1); foundCount++; } } if (string.IsNullOrEmpty(result[0])) ShowErrorDialog($"未找到工序数据!配置:行{AppConfig.Excel.OpRow} 列{AppConfig.Excel.OpCol}"); if (string.IsNullOrEmpty(result[1])) ShowErrorDialog($"未找到刀具数据!配置:行{AppConfig.Excel.ToolRow} 列{AppConfig.Excel.ToolCol}"); if (string.IsNullOrEmpty(result[2])) ShowErrorDialog($"未找到方法数据!配置:行{AppConfig.Excel.MethodRow} 列{AppConfig.Excel.MethodCol}"); if (string.IsNullOrEmpty(result[3])) ShowErrorDialog($"未找到模板数据!配置:行{AppConfig.Excel.TemplateRow} 列{AppConfig.Excel.TemplateCol}"); if (string.IsNullOrEmpty(result[4])) ShowErrorDialog($"未找到程序组数据!配置:行{AppConfig.Excel.ProgramRow} 列{AppConfig.Excel.ProgramCol}"); if (string.IsNullOrEmpty(result[5])) ShowErrorDialog($"未找到几何体数据!配置:行{AppConfig.Excel.GeomRow} 列{AppConfig.Excel.GeomCol}"); if (result.Any(string.IsNullOrEmpty)) return null; } } _cachedExcelData = result; _cachedExcelHash = currentHash; _excelCacheTimestamp = DateTime.Now; return result; } catch (Exception ex) { ShowErrorDialog($"读取Excel失败:{ex.Message}"); return null; } } // 修复:添加ComputeFileHash方法完整实现 private static string ComputeFileHash(string path) { try { using (var md5 = MD5.Create()) using (var stream = File.OpenRead(path)) { byte[] hashBytes = md5.ComputeHash(stream); return BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); } } catch (Exception ex) { ShowErrorDialog($"计算文件哈希失败:{ex.Message}"); return null; } } private static NCGroup[] FindCamGroupsByConfig(string[] excelData) { if (_cachedCamGroupsDict == null || _cachedCamGroupsDict.Count == 0) return null; var groups = new NCGroup[4]; var targetNames = new[] { excelData[4], excelData[1], excelData[5], excelData[2] }; NCGroup firstGroup = _cachedCamGroupsDict.Values.FirstOrDefault(); for (int i = 0; i < targetNames.Length; i++) { if (!string.IsNullOrEmpty(targetNames[i]) && _cachedCamGroupsDict.TryGetValue(targetNames[i], out NCGroup group)) { groups[i] = group; } else if (firstGroup != null) { groups[i] = firstGroup; } } return groups; } private static void OpenOperationDialog(NXOpen.CAM.Operation operation) { _ufSession.Ui.LockUgAccess(1); try { _ufSession.UiOnt.ExpandView(); int response; _ufSession.UiParam.EditObject(operation.Tag, out response); } finally { _ufSession.Ui.UnlockUgAccess(1); } } public static int GetUnloadOption(string dummy) { return (int)Session.LibraryUnloadOption.AtTermination; } } }把这个代码给我出一个完整的思维导图生成一个
最新发布
11-18
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值