Files
2026-06-05 15:58:03 +07:00

320 lines
14 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace QWERTYkez.ExcelProcessor;
/// <summary>
/// Статический класс для работы с документами Excel через процессоры чтения/записи.
/// </summary>
public static class ExcelProcessor
{
#region Read Operations
/// <summary>
/// Пытается открыть документ только для чтения и выполнить действия.
/// </summary>
/// <param name="sourcePath">Путь к исходному файлу .xlsx</param>
/// <param name="read">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryRead(string sourcePath, Action<IExcelReader> read)
{
return TryRead(new FileInfo(sourcePath), read);
}
/// <summary>
/// Пытается открыть документ только для чтения и выполнить действия.
/// </summary>
/// <param name="sourceFile">Объект <see cref="FileInfo"/> исходного файла .xlsx</param>
/// <param name="read">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryRead(FileInfo sourceFile, Action<IExcelReader> read)
{
if (sourceFile is null || read is null)
{
#if DEBUG
Debug.WriteLine("[DEBUG] SourceFile or action is null");
#endif
return false;
}
using var processor = ExcelReader.CreateInternal(sourceFile);
if (processor is null)
return false;
try
{
read(processor);
return true;
}
catch (Exception ex)
{
#if DEBUG
Debug.WriteLine($"[DEBUG] Error in read action: {ex.Message}");
#endif
return false;
}
}
#endregion
#region Read Operations from Memory
/// <summary>
/// Пытается открыть документ из массива байт только для чтения и выполнить действия.
/// </summary>
/// <param name="data">Массив байт, содержащий документ .xlsx</param>
/// <param name="read">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryRead(byte[] data, Action<IExcelReader> read)
=> TryRead(new ReadOnlyMemory<byte>(data), read);
/// <summary>
/// Пытается открыть документ из <see cref="ReadOnlyMemory{byte}"/> только для чтения и выполнить действия.
/// </summary>
/// <param name="data">Буфер с документом .xlsx</param>
/// <param name="read">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryRead(ReadOnlyMemory<byte> data, Action<IExcelReader> read)
{
if (data.IsEmpty || read is null)
{
#if DEBUG
Debug.WriteLine("[DEBUG] Data is empty or action is null");
#endif
return false;
}
using var processor = ExcelReader.CreateFromData(data);
if (processor is null)
return false;
try
{
read(processor);
return true;
}
catch (Exception ex)
{
#if DEBUG
Debug.WriteLine($"[DEBUG] Error in read action from memory: {ex.Message}");
#endif
return false;
}
}
#endregion
#region Write Operations
/// <summary>
/// Пытается открыть документ для записи и выполнить действия с последующей перезаписью исходного файла.
/// </summary>
/// <param name="sourcePath">Путь к исходному файлу .xlsx</param>
/// <param name="write">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryWrite(string sourcePath, Action<IExcelWriter> write)
{
return TryWrite(sourcePath, sourcePath, write);
}
/// <summary>
/// Пытается открыть документ для записи и выполнить действия с последующей перезаписью исходного файла.
/// </summary>
/// <param name="sourceFile">Объект <see cref="FileInfo"/> исходного файла .xlsx</param>
/// <param name="write">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryWrite(FileInfo sourceFile, Action<IExcelWriter> write)
{
return TryWrite(sourceFile, sourceFile.FullName, write);
}
/// <summary>
/// Пытается открыть документ для записи, выполнить действия и сохранить результат по новому пути.
/// </summary>
/// <param name="sourcePath">Путь к исходному файлу .xlsx</param>
/// <param name="destinationPath">Путь для сохранения результата (null - перезапись исходного файла)</param>
/// <param name="write">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryWrite(string sourcePath, string? destinationPath, Action<IExcelWriter> write)
{
return TryWrite(new FileInfo(sourcePath), destinationPath, write);
}
/// <summary>
/// Пытается открыть документ для записи, выполнить действия и сохранить результат по новому пути.
/// </summary>
/// <param name="sourceFile">Объект <see cref="FileInfo"/> исходного файла .xlsx</param>
/// <param name="destinationPath">Путь для сохранения результата (null - перезапись исходного файла)</param>
/// <param name="write">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryWrite(FileInfo sourceFile, string? destinationPath, Action<IExcelWriter> write)
{
if (sourceFile is null || write is null)
{
#if DEBUG
Debug.WriteLine("[DEBUG] SourceFile or action is null");
#endif
return false;
}
using var processor = ExcelWriter.CreateInternal(sourceFile, destinationPath);
if (processor is null)
return false;
try
{
write(processor);
return true;
}
catch (Exception ex)
{
#if DEBUG
Debug.WriteLine($"[DEBUG] Error in write action: {ex.Message}");
#endif
return false;
}
}
#endregion
#region Write Operations from Memory
/// <summary>
/// Пытается открыть документ из массива байт для записи, выполнить действия и сохранить результат по указанному пути.
/// </summary>
/// <param name="data">Массив байт, содержащий документ .xlsx</param>
/// <param name="destinationPath">Путь для сохранения результата</param>
/// <param name="write">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryWrite(byte[] data, string destinationPath, Action<IExcelWriter> write)
=> TryWrite(new ReadOnlyMemory<byte>(data), destinationPath, write);
/// <summary>
/// Пытается открыть документ из <see cref="ReadOnlyMemory{byte}"/> для записи, выполнить действия и сохранить результат по указанному пути.
/// </summary>
/// <param name="data">Буфер с документом .xlsx</param>
/// <param name="destinationPath">Путь для сохранения результата</param>
/// <param name="write">Действия для выполнения над документом</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/></returns>
public static bool TryWrite(ReadOnlyMemory<byte> data, string destinationPath, Action<IExcelWriter> write)
{
if (data.IsEmpty || write is null)
{
#if DEBUG
Debug.WriteLine("[DEBUG] Data is empty or action is null");
#endif
return false;
}
using var processor = ExcelWriter.CreateFromData(data, destinationPath);
if (processor is null)
return false;
try
{
write(processor);
return true;
}
catch (Exception ex)
{
#if DEBUG
Debug.WriteLine($"[DEBUG] Error in write action from memory: {ex.Message}");
#endif
return false;
}
}
#endregion
/// <summary>
/// Пытается создать новый документ Excel, отредактировать его и вернуть результат в виде массива байт.
/// </summary>
/// <param name="result">Результирующий массив байт (если операция успешна).</param>
/// <param name="write">Действия для заполнения документа.</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/>.</returns>
public static bool TryCreate(out byte[] result, Action<IExcelWriter> write)
{
result = null!;
if (write is null) return false;
try
{
using var writer = ExcelWriter.CreateNew();
write(writer);
result = writer.GetDocumentBytes(); // добавим этот метод в ExcelWriter
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Пытается создать новый документ Excel, отредактировать его и записать в указанный поток.
/// </summary>
/// <param name="outputStream">Поток, в который будет записан документ.</param>
/// <param name="write">Действия для заполнения документа.</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/>.</returns>
public static bool TryCreate(Stream outputStream, Action<IExcelWriter> write)
{
if (write is null || outputStream is null) return false;
try
{
using var writer = ExcelWriter.CreateNew();
write(writer);
writer.SaveTo(outputStream);
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Пытается создать новый документ Excel, отредактировать его и сохранить на диск.
/// </summary>
/// <param name="destinationPath">Путь для сохранения результата.</param>
/// <param name="write">Действия для заполнения документа.</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/>.</returns>
public static bool TryCreate(string destinationPath, Action<IExcelWriter> write)
{
if (string.IsNullOrEmpty(destinationPath) || write is null)
return false;
try
{
using var writer = ExcelWriter.CreateNew(destinationPath);
write(writer);
writer.Save();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Пытается создать новый документ Excel, отредактировать его и прочитать результат в памяти.
/// </summary>
/// <param name="write">Действия для заполнения документа.</param>
/// <param name="read">Действия для чтения полученного документа.</param>
/// <returns><see langword="true"/> если операция выполнена успешно, иначе <see langword="false"/>.</returns>
public static bool TryRead(Action<IExcelWriter> write, Action<IExcelReader> read)
{
if (write is null || read is null)
return false;
try
{
using var writer = ExcelWriter.CreateNew();
write(writer);
using var reader = writer.ToReader();
read(reader);
return true;
}
catch
{
return false;
}
}
}