На работе постоянно приходится печатать маленькие этикетки для груза. На данный момент заполняется excel таблица и печатается нужное количество из нее. (примерно такого формата)
Нужно много что заполнить, выделить нужное количество... В общем долго...
Появилась идея сделать небольшую софтину, где нужно заполнить форму и указать количество этих этикеток, софтина бы сама распределила их на странице и отправила в печать.
Как ой подход к данной задаче вы можете предложить?
Мои варианты:
Создать excel файл заполнить его, и напечатать. (если это вообще возможно)
Создать многостраничный документ xps/pdf/word... И печатать его.
Создать набор картинок и печатать их. (наверное самый трудный вариант)
На мой взгляд, проще всего сверстать вашу картинку в WPF-приложении.
Если ваша картинка находится, например, в Grid
'е с именем main
, то вы можете её напечатать при помощи
var dialog = new PrintDialog();
if (dialog.ShowDialog() == true) // возвращает bool?, поэтому сравнение с true
{
dialog.PrintVisual(main, "Вывод этикетки на печать");
}
Ещё документация:
Дополнение: для вёрстки проще всего использовать MVVM. Для вот такого класса:
public class Label
{
public string Address1 { get; set; }
public string Address2 { get; set; }
public string InvoiceNo { get; set; }
public string OrderNo { get; set; }
public string ItemNo { get; set; }
}
и XAML'а
<ItemsControl Width="600" Height="800" ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="150" BorderBrush="Black" BorderThickness="3" Margin="0,0,-3,-3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock FontSize="14" Text="{Binding Address1}" Grid.Row="0" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
<TextBlock FontSize="12" Text="{Binding Address2}" Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
<TextBlock FontSize="13" FontStyle="Italic" Text="Накладная:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center"/>
<TextBlock FontSize="13" Text="{Binding InvoiceNo}" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Center"/>
<TextBlock FontSize="13" FontStyle="Italic" Text="Заказ:" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Center"/>
<TextBlock FontSize="13" Text="{Binding OrderNo}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Center"/>
<TextBlock FontSize="13" FontStyle="Italic" Text="Место:" Grid.Row="4" Grid.Column="0" HorizontalAlignment="Center"/>
<TextBlock FontSize="13" FontWeight="Bold" Text="{Binding ItemNo}" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
и DataContext
'а
new[]
{
new Label()
{
Address1 = "Куда-то там",
Address2 = "Адрес 4",
InvoiceNo = "2222222222",
OrderNo = "1111111111",
ItemNo = "1"
},
new Label()
{
Address1 = "Куда-то там",
Address2 = "Адрес 4",
InvoiceNo = "2222222222",
OrderNo = "1111111111",
ItemNo = "2"
}
}
получается следующая картинка:
(Понятно, DataContext
лучше генерировать в цикле.)
Если надо вывести несколько страниц, можно просто вызвать PrintVisual
в цикле несколько раз. Однако это создаст несколько заданий на печать. Чтобы оформить это всё как одно задание, нужно предоставить DocumentPaginator
и вызвать dialog.PrintDocument
вместо PrintVisual
. Набросал простейшую имплементацию:
public class Paginator : DocumentPaginator
{
Visual[] pages;
public Paginator(params Visual[] pages)
{
this.pages = pages;
this.Source = new S() { DocumentPaginator = this };
}
public override bool IsPageCountValid => true;
public override int PageCount => pages.Length;
public override Size PageSize { get; set; }
class S : IDocumentPaginatorSource
{
public DocumentPaginator DocumentPaginator { get; set; }
}
public override IDocumentPaginatorSource Source { get; }
public override DocumentPage GetPage(int pageNumber) =>
new DocumentPage(pages[pageNumber]);
}
Печатать так:
var dialog = new PrintDialog();
if (dialog.ShowDialog() == true) // возвращает bool?, поэтому сравнение с true
{
dialog.PrintDocument(new Paginator(grid1, grid2, grid3), "Вывод этикетки на печать");
}
Вообще, из предложенных вам пунктов, последний наверное самый простой. Просто рисуете через GDI и все. Вот тут - https://msdn.microsoft.com/en-us/library/bb383872(v=vs.90).aspx можно почитать.
Другой момент, можно работать с excel через Interop (ole) - https://stackoverflow.com/questions/854693/printing-excel-using-interop . Так же можно и взаимодействовать с книгой и страницами. Но, это требует обязательно установленного Excel-я.
По поводу Pdf - как по мне, реализация отрисовки изображений сопоставима по объему кода с реализацией логики отрисовки PDF. Поэтому, тут уже кому как удобнее.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Я хочу сделать полоску над врагом, получается вот это:
Так исторически сложилось, что необходимо использовать TextBox для ввода логина и пароляКак правильно организовать замену символов в текстовом...