wkhtmltopdf номера страниц [дубликат]

TL; DR: Попробуйте использовать Html.Partial вместо Renderpage


Я получал Object reference not set to an instance of an object, когда пытался сделать вид в представлении, отправив ему модель, например это:

@{
    MyEntity M = new MyEntity();
}
@RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null

Отладка показала, что модель была Null внутри MyOtherView. Пока я не сменил его на:

@{
    MyEntity M = new MyEntity();
}
@Html.Partial("_MyOtherView.cshtml", M);

И это сработало.

Кроме того, причина, по которой я не имел Html.Partial для начала, заключалась в том, что Visual Studio иногда выдает ошибки, (f9), если он находится внутри другого построенного цикла foreach, хотя это не ошибка:

@inherits System.Web.Mvc.WebViewPage
@{
    ViewBag.Title = "Entity Index";
    List<MyEntity> MyEntities = new List<MyEntity>();
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
    MyEntities.Add(new MyEntity());
}
<div>
    @{
        foreach(var M in MyEntities)
        {
            // Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
            @Html.Partial("MyOtherView.cshtml");
        }
    }
</div>

Но я смог запустить приложение без проблем с этим " ошибка". Я смог избавиться от ошибки, изменив структуру цикла foreach, чтобы выглядеть так:

@foreach(var M in MyEntities){
    ...
}

Хотя я чувствую, что это потому, что Visual Studio неправильно интерпретировала амперсанды и скобки .

35
задан Tamás Barta 24 August 2011 в 12:00
поделиться

6 ответов

Чтобы показать номер страницы и общие страницы, вы можете использовать этот фрагмент javascript в нижнем колонтитуле или коде заголовка:

  var pdfInfo = {};
  var x = document.location.search.substring(1).split('&');
  for (var i in x) { var z = x[i].split('=',2); pdfInfo[z[0]] = unescape(z[1]); }
  function getPdfInfo() {
    var page = pdfInfo.page || 1;
    var pageCount = pdfInfo.topage || 1;
    document.getElementById('pdfkit_page_current').textContent = page;
    document.getElementById('pdfkit_page_count').textContent = pageCount;
  }

И вызвать getPdfInfo со страницей onload

Конечно, pdfkit_page_current и pdfkit_page_count будут двумя элементами, отображающими числа.

Фрагмент, взятый из здесь

20
ответ дан Dan Mazzini 24 August 2018 в 02:28
поделиться

На самом деле это намного проще, чем с фрагментом кода. Вы можете добавить следующий аргумент в командной строке: --footer-center [page]/[topage].

Как упоминалось в Richard, дополнительные переменные находятся в разделе Footers and Headers документации .

53
ответ дан aknuds1 24 August 2018 в 02:28
поделиться

Безопасный подход, даже если вы используете XHTML (например, с тимелеафом). Единственное отличие от решения другого - использование // тэгов.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <script>
        /*<![CDATA[*/
        function subst() {
            var vars = {};
            var query_strings_from_url = document.location.search.substring(1).split('&');
            for (var query_string in query_strings_from_url) {
                if (query_strings_from_url.hasOwnProperty(query_string)) {
                    var temp_var = query_strings_from_url[query_string].split('=', 2);
                    vars[temp_var[0]] = decodeURI(temp_var[1]);
                }
            }
            var css_selector_classes = ['page', 'topage'];
            for (var css_class in css_selector_classes) {
                if (css_selector_classes.hasOwnProperty(css_class)) {
                    var element = document.getElementsByClassName(css_selector_classes[css_class]);
                    for (var j = 0; j < element.length; ++j) {
                        element[j].textContent = vars[css_selector_classes[css_class]];
                    }
                }
            }
        }
        /*]]>*/
    </script>
</head>
<body onload="subst()">
    <div class="page-counter">Page <span class="page"></span> of <span class="topage"></span></div>
</body>

Последнее примечание: при использовании тимелеафа замените <script> на <script th:inline="javascript">.

1
ответ дан Juangui Jordán 24 August 2018 в 02:28
поделиться

То, как это должно быть сделано (то есть, если wkhtmltopdf поддерживает его), будет использоваться правильный CSS Paged Media: http://www.w3.org/TR/css3-gcpm/

Я изучаю, что это займет сейчас.

1
ответ дан rainabba 24 August 2018 в 02:28
поделиться

В документации wkhtmltopdf ( http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf-0.9.9-doc.html ) под заголовком «Нижние колонтитулы и заголовки» есть фрагмент кода для достижения нумерации страниц:

<html><head><script>
function subst() {
  var vars={};
  var x=document.location.search.substring(1).split('&');
  for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}
  var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];
  for(var i in x) {
    var y = document.getElementsByClassName(x[i]);
    for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];
  }
}
</script></head><body style="border:0; margin: 0;" onload="subst()">
<table style="border-bottom: 1px solid black; width: 100%">
  <tr>
    <td class="section"></td>
    <td style="text-align:right">
      Page <span class="page"></span> of <span class="topage"></span>
    </td>
  </tr>
</table>
</body></html>

Существуют также более доступные переменные, которые можно заменить, кроме номеров страниц, для использования в верхних колонтитулах.

14
ответ дан Tamás Barta 24 August 2018 в 02:28
поделиться

Среди нескольких других параметров номер страницы и общий номер страницы передаются в HTML-код нижнего колонтитула как параметры запроса, как указано в официальных документах:

... [номер страницы ] аргументы отправляются в html-документы заголовка / нижнего колонтитула в модуле GET.

Источник: http://wkhtmltopdf.org/usage/wkhtmltopdf.txt

Таким образом, решение состоит в том, чтобы получить эти параметры, используя бит JS и превращая их в шаблон HTML. Вот полный рабочий пример HTML нижнего колонтитула:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <script>
        function substitutePdfVariables() {

            function getParameterByName(name) {
                var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
                return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
            }

            function substitute(name) {
                var value = getParameterByName(name);
                var elements = document.getElementsByClassName(name);

                for (var i = 0; elements && i < elements.length; i++) {
                    elements[i].textContent = value;
                }
            }

            ['frompage', 'topage', 'page', 'webpage', 'section', 'subsection', 'subsubsection']
                .forEach(function(param) {
                    substitute(param);
                });
        }
    </script>
</head>
<body onload="substitutePdfVariables()">
    <p>Page <span class="page"></span> of <span class="topage"></span></p>
</body>
</html>

substitutePdfVariables() вызывается в теле onload. Затем мы получаем каждую поддерживаемую переменную из строки запроса и заменяем содержимое во всех элементах соответствующим именем класса.

27
ответ дан theDmi 24 August 2018 в 02:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: