Строковые замены для Word Merge - PullRequest
0 голосов
/ 31 марта 2011

используя asp.net 4

мы делаем много слияний Word на работе. вместо того, чтобы использовать сложные условные выражения Word, я хочу встроить свой собственный синтаксис. что-то вроде:

Dear Mr. { select lastname from users where userid = 7 },
Your invoice for this quarter is: ${ select amount from invoices where userid = 7 }.
......

в идеале, я бы хотел, чтобы это превратилось в:

string.Format("Dear Mr. {0},  Your invoice for this quarter is: ${1}", sqlEval[0], sqlEval[1]);

есть идеи?

Ответы [ 4 ]

0 голосов
/ 01 апреля 2011

я закончил кататься, но спасибо.Мне действительно не нравятся заявления.Мне нужно их рефакторинг.вот оно:

var mailingMergeString = new MailingMergeString(input);
var output = mailingMergeString.ParseMailingMergeString();

public class MailingMergeString
{
    private string _input;

    public MailingMergeString(string input)
    {
        _input = input;
    }

    public string ParseMailingMergeString()
    {
        IList<SqlReplaceCommand> sqlCommands = new List<SqlReplaceCommand>();
        var i = 0;
        const string openBrace = "{";
        const string closeBrace = "}";

        while (string.IsNullOrWhiteSpace(_input) == false)
        {
            var sqlReplaceCommand = new SqlReplaceCommand();
            var open = _input.IndexOf(openBrace) + 1;
            var close = _input.IndexOf(closeBrace);
            var length = close != -1 ? close - open : _input.Length;
            var newInput = _input.Substring(close + 1);
            var nextClose = newInput.Contains(openBrace) ? newInput.IndexOf(openBrace) : newInput.Length;

            if (i == 0 && open > 0)
            {
                sqlReplaceCommand.Text = _input.Substring(0, open - 1);
                _input = _input.Substring(open - 1);
            }
            else
            {
                sqlReplaceCommand.Command = _input.Substring(open, length);
                sqlReplaceCommand.PlaceHolder = openBrace + i + closeBrace;
                sqlReplaceCommand.Text = _input.Substring(close + 1, nextClose);
                sqlReplaceCommand.NewInput = _input.Substring(close + 1);

                _input = newInput.Contains(openBrace) ? sqlReplaceCommand.NewInput : string.Empty;
            }

            sqlCommands.Add(sqlReplaceCommand);
            i++;
        }

        return sqlCommands.GetParsedString();
    }

    internal class SqlReplaceCommand
    {
        public string Command { get; set; }

        public string SqlResult { get; set; }

        public string PlaceHolder { get; set; }

        public string Text { get; set; }

        protected internal string NewInput { get; set; }
    }
}

internal static class SqlReplaceExtensions
{
    public static string GetParsedString(this IEnumerable<MailingMergeString.SqlReplaceCommand> sqlCommands)
    {
        return sqlCommands.Aggregate("", (current, replaceCommand) => current + (replaceCommand.PlaceHolder + replaceCommand.Text));
    }
}
0 голосов
/ 01 апреля 2011

Я только что закончил создание подобного решения для юридической фирмы здесь.Я оценил продукт под названием Windward reports.Это немного дорого, особенно если вам нужно много копий, но для одного пользователя это неплохо.

он может извлекать данные из источников данных XML или SQL (или больше, если я помню).

Может стоит посмотреть (и нет, я не работаю на них, просто оценил их вещи)

0 голосов
/ 01 апреля 2011

Возможно, вы захотите проверить проект движка бритвы на codeplex

http://razorengine.codeplex.com/

Использование SQL и т. Д. В вашем шаблоне выглядит плохой идеей.Я бы посоветовал вам сделать ViewModel для каждого шаблона.

Razor действительно прост в использовании.Просто добавьте ссылку, импортируйте пространство имен и вызовите метод Parse следующим образом:

(парень из VB, извините за синтаксис!)

MyViewModel myModel = new MyViewModel("Bob",150.00); //set properties

string myTemplate = "Dear Mr. @Model.FirstName,  Your invoice for this quarter is: @Model.InvoiceAmount";

string myOutput = Razor.Parse(myTemplate, myModel);

Ваша строка может прийти откуда угодно - я использую этос моими шаблонами, хранящимися в базе данных, вы можете загрузить его из файлов или чего-то еще.Он очень мощный как движок представления, вы можете выполнять условные операции, циклы и т. Д. И т. Д.

0 голосов
/ 01 апреля 2011

Что ж, я не рекомендую использовать для этого собственное решение, однако я отвечу на вопрос в том виде, в котором он был задан.

Сначала вам нужно обработать текст и извлечь операторы SQL.Для этого вам понадобится простой парсер:

/// <summary>Parses the input string and extracts a unique list of all placeholders.</summary>
/// <remarks>
///  This method does not handle escaping of delimiters
/// </remarks>
public static IList<string> Parse(string input)
{
    const char placeholderDelimStart = '{';
    const char placeholderDelimEnd = '}';

    var characters = input.ToCharArray();
    var placeHolders = new List<string>();
    string currentPlaceHolder = string.Empty;
    bool inPlaceHolder = false;
    for (int i = 0; i < characters.Length; i++)
    {
        var currentChar = characters[i];

        // Start of a placeholder
        if (!inPlaceHolder && currentChar == placeholderDelimStart)
        {
            currentPlaceHolder = string.Empty;
            inPlaceHolder = true;
            continue;
        }

        // Start of a placeholder when we already have one
        if (inPlaceHolder && currentChar == placeholderDelimStart)
            throw new InvalidOperationException("Unexpected character detected at position " + i);

        // We found the end marker while in a placeholder - we're done with this placeholder
        if (inPlaceHolder && currentChar == placeholderDelimEnd)
        {
            if (!placeHolders.Contains(currentPlaceHolder))
                placeHolders.Add(currentPlaceHolder);
            inPlaceHolder = false;
            continue;
        }

        // End of a placeholder with no matching start
        if (!inPlaceHolder && currentChar == placeholderDelimEnd)
            throw new InvalidOperationException("Unexpected character detected at position " + i);

        if (inPlaceHolder)
            currentPlaceHolder += currentChar;
    }
    return placeHolders;
}

Хорошо, так что вы получите список операторов SQL, извлеченных из входного текста.Возможно, вы захотите настроить его так, чтобы использовать правильно типизированные исключения синтаксического анализатора и некоторые средства защиты ввода (которые я исключил для ясности).

Теперь вам просто нужно заменить эти заполнители на результаты вычисленного SQL:

// Sample input
var input = "Hello Mr. {select firstname from users where userid=7}";

string output = input;
var extractedStatements = Parse(input);
foreach (var statement in extractedStatements)
{
    // Execute the SQL statement
    var result = Evaluate(statement);

    // Update the output with the result of the SQL statement
    output = output.Replace("{" + statement + "}", result);
}

Это, очевидно, не самый эффективный способ сделать это, но я думаю, что он в достаточной мере демонстрирует концепцию, не пачкая воды.

Вам нужно будет определить метод Evaluate(string).Это будет обрабатывать выполнение SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...