如何高效解析PDF导出的采购订单字符串至对象变量
采购订单字符串高效解析方案
问题背景
有从PDF导出的固定格式采购订单字符串,示例如下:
1 EA 2.00 2814-212-D003 0.00 0.00 LONG JACK PAD Drawing: OPT Due: 05/19/2023 Requester: NMB Order: 2843HR-213-703 Seq No: 9002 2 EA 2.00 2814-212-D003 0.00 0.00 LONG JACK PAD Drawing: OPT Due: 05/19/2023 Requester: NMB Order: 2843HR-214-703 Seq No: 9002 3 EA 2.00 2814-212-D004 0.00 0.00 SHORT JACK PAD Drawing: OPT Due: 05/19/2023 Requester: NMB Order: 2843HR-213-703 Seq No: 9003 4 EA 2.00 2814-212-D004 0.00 0.00 SHORT JACK PAD Drawing: OPT Due: 05/19/2023 Requester: NMB Order: 2843HR-214-703 Seq No: 9003
需要提取每个条目的行号、数量、零件号、描述、绘图来源、到期日,存入自定义对象后导入Excel。当前用Substring实现逻辑混乱,求更高效的解析方式。
高效解析方案
方法1:按行分割+分组解析(直观可靠)
每个条目固定占7行,先把文本按行拆分,过滤空行后每7行作为一组提取数据:
首先定义自定义对象:
public class PurchaseOrderItem { public int LineNumber { get; set; } public decimal Quantity { get; set; } public string PartNumber { get; set; } public string Description { get; set; } public string DrawingSource { get; set; } public DateTime DueDate { get; set; } }
解析代码:
string rawText = richTextBox1.Text; // 拆分行并过滤空行/纯空白行 var lines = rawText.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries) .Where(line => !string.IsNullOrWhiteSpace(line)) .ToList(); var orderItems = new List<PurchaseOrderItem>(); // 每7行一组循环处理 for (int i = 0; i < lines.Count; i += 7) { var item = new PurchaseOrderItem(); // 提取行号(第1行) item.LineNumber = int.Parse(lines[i].Trim()); // 提取数量、零件号(第3行,跳过第2行的EA) var partsLine = lines[i+2].Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); item.Quantity = decimal.Parse(partsLine[0]); item.PartNumber = partsLine[1]; // 提取描述(第4行) item.Description = lines[i+3].Trim(); // 提取绘图来源(第5行,冒号后内容) item.DrawingSource = lines[i+4].Split(':')[1].Trim(); // 提取到期日(第6行,冒号后、Requester前的内容) var dueLine = lines[i+5].Split(new[] { "Requester:" }, StringSplitOptions.None); var dueDateStr = dueLine[0].Split(':')[1].Trim(); item.DueDate = DateTime.Parse(dueDateStr); orderItems.Add(item); }
这种方法逻辑清晰,易维护,适合格式完全固定的场景。
方法2:正则表达式匹配(适配小变动)
如果行结构偶尔有微小变动(比如随机空行),可以用正则匹配完整条目:
// 正则匹配每个完整条目,可根据实际格式调整 string pattern = @"(?<LineNumber>\d+)\s+EA\s+(?<Quantity>\d+\.\d+)\s+(?<PartNumber>\w+-\w+-\w+)\s+\d+\.\d+\s+\d+\.\d+\s+(?<Description>.+?)\s+Drawing:\s+(?<DrawingSource>.+?)\s+Due:\s+(?<DueDate>\d{2}/\d{2}/\d{4})"; var regex = new Regex(pattern, RegexOptions.Singleline); var matches = regex.Matches(rawText); var orderItems = new List<PurchaseOrderItem>(); foreach (Match match in matches) { var item = new PurchaseOrderItem { LineNumber = int.Parse(match.Groups["LineNumber"].Value), Quantity = decimal.Parse(match.Groups["Quantity"].Value), PartNumber = match.Groups["PartNumber"].Value, Description = match.Groups["Description"].Value.Trim(), DrawingSource = match.Groups["DrawingSource"].Value.Trim(), DueDate = DateTime.Parse(match.Groups["DueDate"].Value) }; orderItems.Add(item); }
正则的优点是兼容小格式变动,缺点是编写和调试稍复杂。
方案对比
- 按行分组:代码直观,易调试,适合格式稳定的场景。
- 正则表达式:灵活性强,能适配格式小变化,适合复杂格式场景。
内容的提问来源于stack exchange,提问作者Jfisher387
相关产品推荐
相关产品推荐

