public static IEnumerable <IMergeError> ReplaceMergeFieldsAndReturnMissingFieldNames( XmlDocument sharedStringsDoc, List <XmlDocument> sheetDocList, Dictionary <string, string> replacements, Engine engine) { var fields = GetSharedStrings(sharedStringsDoc); var errors = new List <IMergeError>(); var properties = new Properties(replacements); int stringIdx = 0; foreach (var field in fields) { var value = field.Text; var matches = regex.Match(field.Text); if (matches.Success) { var fieldNames = matches.Groups["name"].Captures; var fieldTemplates = matches.Groups["template"].Captures; for (var fieldIdx = 0; fieldIdx < fieldNames.Count; ++fieldIdx) { var fieldName = fieldNames[fieldIdx].ToString(); var fieldTemlate = fieldTemplates[fieldIdx].ToString(); var exp = engine.Parse(fieldName); if (exp == null) { errors.Add(new MergeError(v => v.InvalidExpression(fieldName))); } else { var missingProperties = new List <string>(); properties.FindMissingProperties(exp, missingProperties); errors.AddRange(missingProperties.Select(p => new MergeError(v => v.MissingField(p)))); if (missingProperties.Count == 0) // otherwise Eval will throw { value = value.Replace(fieldTemlate, properties.Eval(exp)); } } } if (value != field.Text) { double dresult; if (Double.TryParse(value.Trim(), out dresult)) { foreach (var sheetDoc in sheetDocList) { var cells = GetStringCells(sheetDoc, stringIdx); foreach (var cell in cells) { cell.DoubleValue = dresult; } } value = ""; } } field.StringValue = value; } ++stringIdx; } return(errors); }