Как добавить водяные знаки в Excel на C#: два практических подхода
При распространении отчетов, архивировании договоров и обмене конфиденциальными данными добавление водяного знака в документ Excel является простым и практичным способом определения авторских прав. Водяной знак может представлять собой изображение или текст. Водяные надписи «Конфиденциально», «Только для внутреннего пользования», «Запрещено распространять» широко используются в бизнес-процессах по всему миру.
В данной статье показано, как с помощью бесплатной библиотеки .NET для работы с Excel добавлять водяные знаки в документы Excel на языке C#. Сравниваются два метода реализации: водяной знак в виде изображения в колонтитуле и водяной знак на фоне листа. Также предоставлен вспомогательный код для генерации изображений текстовых водяных знаков — он подходит для использования даже при отсутствии готового файла водяного знака.
Установка
Библиотека подключается к проекту через NuGet.
Консоль диспетчера пакетов NuGet
Install-Package FreeSpire.XLS
Интерфейс командной строки .NET CLI
dotnet add package FreeSpire.XLS
После завершения установки импортируйте пространство имен Spire.Xls в код для работы с библиотекой.
Сравнение двух решений для водяных знаков
В Excel нет отдельного объекта «водяной знак». Имитация водяного знака реализуется либо через изображение в колонтитуле, либо через фоновое изображение листа. Поэтому два подхода существенно различаются по выводу на печать, отображению на экране, позиционированию и другим параметрам.
Водяной знак в колонтитуле
Преимущества : водяной знак сохраняется при печати документа, подходит для сценариев с обязательной печатью и архивированием файлов.
Недостатки : не виден в обычном режиме Excel, отображается только в режимах разметки страницы и просмотра разрывов; для точного центрирования изображения на странице требуется тщательная настройка верхних и левых полей.
Фоновый водяной знак листа
Преимущества : изображение покрывает весь лист, обеспечивается единообразный визуальный эффект.
Недостатки : водяной знак не выводится на печать.
Решение 1: Добавление водяного знака через колонтитул
В следующем примере выполняется обход всех листов документа и установка одного и того же изображения водяного знака по центру колонтитула.
using SkiaSharp;
using Spire.Xls;
namespace AddWatermarkToExcelUsingHeader
{
class Program
{
static void Main(string[] args)
{
// Создание объекта книги Excel
Workbook workbook = new Workbook();
// Загрузка документа Excel
workbook.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");
// Загрузка изображения водяного знака
SkiaSharp.SKImage image = SkiaSharp.SKImage.FromEncodedData(@"C:\Users\Administrator\Desktop\confidential.png");
// Обход всех листов документа
for (int i = 0; i < workbook.Worksheets.Count; i++)
{
// Получение нужного листа
Worksheet worksheet = workbook.Worksheets[i];
// Вставка маркера изображения по центру верхнего колонтитула
worksheet.PageSetup.CenterHeader = "&G";
// Присвоение изображения центральной части колонтитула
worksheet.PageSetup.CenterHeaderImage = SKBitmap.FromImage(image);
}
// Сохранение итогового файла
workbook.SaveToFile("AddWatermark.xlsx", ExcelVersion.Version2016);
// Освобождение ресурсов
workbook.Dispose();
}
}
}
Примечание: &G — собственный маркер изображения в колонтитулах Excel. Все надписи (например, слово «Конфиденциально») должны быть встроены непосредственно в изображение, а не записаны в строку CenterHeader.
Решение 2: Установка изображения как фон листа
Данный пример использует изображение как фоновый водяной знак листа, подходит для сценариев только экранного просмотра, где важна хорошая видимость отметки.
using SkiaSharp;
using Spire.Xls;
namespace AddWatermarkToExcelUsingBackground
{
class Program
{
static void Main(string[] args)
{
// Создание объекта книги Excel
Workbook workbook = new Workbook();
// Загрузка документа Excel
workbook.LoadFromFile(@"C:\Users\Administrator\Desktop\Input.xlsx");
// Загрузка изображения водяного знака как битмап
SkiaSharp.SKImage image = SkiaSharp.SKImage.FromEncodedData(@"C:\Users\Administrator\Desktop\confidential.png");
// Обход всех листов документа
for (int i = 0; i < workbook.Worksheets.Count; i++)
{
// Получение нужного листа
Worksheet worksheet = workbook.Worksheets[i];
// Установка изображения как фон листа
worksheet.PageSetup.BackgoundImage = SKBitmap.FromImage(image);
}
// Сохранение итогового файла
workbook.SaveToFile("AddWatermark.xlsx", ExcelVersion.Version2016);
// Освобождение ресурсов
workbook.Dispose();
}
}
}
Генерация текстовых водяных знаков (реализация через SkiaSharp)
В реальных бизнес-сценариях водяные знаки чаще всего представляют собой динамический текст, например «Конфиденциально», «Только для внутреннего пользования». Не требуется каждый раз обращаться к дизайнеру за готовыми файлами PNG. С помощью библиотеки SkiaSharp можно отрисовать изображение текстового водяного знака с прозрачным фоном прямо в оперативной памяти, после чего результат подходит для использования с двумя описанными выше способами добавления водяных знаков.
using SkiaSharp;
public static class WatermarkHelper
{
/// <summary>
/// Генерация битмапа текстового водяного знака на основе SkiaSharp (прозрачный фон, наклон -30°)
/// </summary>
/// <param name="text">Текст водяного знака, пример: «Конфиденциально»</param>
/// <param name="width">Ширина холста</param>
/// <param name="height">Высота холста</param>
/// <returns>Объект SKBitmap с поддержкой альфа-канала прозрачности</returns>
public static SKBitmap Create(string text, int width, int height)
{
// Создание холста битмапа с альфа-каналом прозрачности
SKBitmap bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
using (SKCanvas canvas = new SKCanvas(bitmap))
using (SKPaint textPaint = new SKPaint())
using (SKTypeface typeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Bold))
{
// Очистка холста, заливка полностью прозрачным фоном
canvas.Clear(SKColors.Transparent);
// Настройка параметров отрисовки текста
textPaint.Typeface = typeface;
textPaint.TextSize = 60;
textPaint.IsAntiAlias = true;
// Красный текст, степень прозрачности 60 (диапазон значений 0–255)
textPaint.Color = new SKColor(255, 0, 0, 60);
// Расчет границ текста для его центрированной отрисовки
SKRect textBounds = new SKRect();
textPaint.MeasureText(text, ref textBounds);
// Сдвиг начала координат в центр холста, поворот против часовой стрелки на 30 градусов
canvas.Translate(width / 2f, height / 2f);
canvas.RotateDegrees(-30);
// Отрисовка текста водяного знака строго по центру
float textX = -textBounds.MidX;
float textY = -textBounds.MidY;
canvas.DrawText(text, textX, textY, textPaint);
}
return bitmap;
}
}
При вызове достаточно присвоить готовый объект SKBitmap свойству фонового изображения листа:
// Вызов вспомогательного класса для генерации битмапа текстового водяного знака
SKBitmap watermarkBitmap = WatermarkHelper.Create("Конфиденциально", 800, 600);
// Установка битмапа как фоновый водяной знак листа
workbook.Worksheets[0].PageSetup.BackgroundImage = watermarkBitmap;
Рекомендации по унификации отображения шрифтов для SkiaSharp
SkiaSharp по умолчанию использует шрифты, установленные на сервере. В окружениях без предустановленных стандартных шрифтов (серверы Linux, контейнеры Docker) возможна автоматическая подмена шрифтов и искажение отображения надписей. Для стабильной работы в промышленной среде предлагаются три решения:
Включить файлы шрифтов формата TTF/OTF как встроенные ресурсы непосредственно в приложение;
Загружать локальные шрифты через метод SKTypeface.FromStream(), не полагаясь на системные шрифты сервера;
Заранее отрисовать все варианты текста водяных знаков, используемых в бизнес-процессах, в виде статических файлов PNG и хранить их как ресурсы проекта — это полностью исключает ошибки отображения из-за отсутствия шрифтов на окружении.
Справочник по выбору решения
Итог
Бесплатная библиотека .NET для работы с Excel не содержит отдельного объекта «водяной знак». Функционал реализуется двумя способами: через изображение в колонтитуле или фоновое изображение листа. Достаточно передать любой объект Image/Bitmap в свойства CenterHeaderImage или BackgroundImage для добавления отметки. В сочетании с небольшим кодом отрисовки текста можно гибко генерировать водяные знаки с надписями «Конфиденциально», «Только для внутреннего пользования» без внешних графических файлов.
В реальных проектах рекомендуется вынести логику «генерации изображения + вставки водяного знака» в отдельные служебные методы, предоставляя внешнему коду минимальный набор параметров: путь к файлу, текст водяного знака, настройки видимости. Это снижает затраты на повторное использование кода при работе с множеством бизнес-направлений и шаблонов документов.













