213 lines
9.1 KiB
C#
213 lines
9.1 KiB
C#
using ClosedXML.Excel;
|
|
using DocumentFormat.OpenXml.Drawing.Charts;
|
|
using DocumentFormat.OpenXml.Spreadsheet;
|
|
using paperless_ngx_export.Models;
|
|
using RBush;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace paperless_ngx_export
|
|
{
|
|
public static class spreadsheet
|
|
{
|
|
public static async Task<byte[]> GetSummarySpreadsheetAsByteArrayAsync()
|
|
{
|
|
byte[] bytes = null;
|
|
|
|
using (var stream = new MemoryStream())
|
|
{
|
|
var workbook = await GetSummaryAsXLWorkbookAsync();
|
|
workbook.SaveAs(stream);
|
|
bytes = stream.ToArray();
|
|
stream.Close();
|
|
}
|
|
|
|
return bytes ?? new byte[0];
|
|
}
|
|
|
|
public static void PopulateDocumentTypeWorksheets(
|
|
IEnumerable<DocumentType> documentTypes,
|
|
IEnumerable<Tag> tags,
|
|
IEnumerable<CustomField> customFields,
|
|
IEnumerable<DocumentParsed> docs,
|
|
XLWorkbook workbook,
|
|
bool onlyCurrentDocuments = true)
|
|
{
|
|
var headings = new string[]
|
|
{
|
|
"Correspondent",
|
|
"Role",
|
|
"Specialty",
|
|
"Document Type",
|
|
"Expiration Date",
|
|
"Tags"
|
|
};
|
|
|
|
var documents = docs.Where(x =>
|
|
{
|
|
if (!x.CustomFields.Any(xx => xx.Name.Contains("expir", StringComparison.OrdinalIgnoreCase)))
|
|
return true;
|
|
|
|
return onlyCurrentDocuments ? !x.Tags.Any(xx => xx.name.Contains("renewed", StringComparison.OrdinalIgnoreCase)) : true;
|
|
}).ToList();
|
|
|
|
foreach (var documentType in documentTypes.OrderBy(x=>!documents.Any(d=>d.DocumentType == x.name && d.CustomFields.Any(cf=>cf.Name.Contains("expir", StringComparison.OrdinalIgnoreCase)))).
|
|
ThenBy(x=>x.name))
|
|
{
|
|
var sheetName = documentType.name.Replace('/', '-');
|
|
var sheet = workbook.Worksheets.FirstOrDefault(x => x.Name == sheetName);
|
|
if (sheet == null)
|
|
{
|
|
sheet = workbook.Worksheets.Add(sheetName);
|
|
sheet.TabColor = XLColor.Green;
|
|
|
|
for (int i = 0; i < headings.Length; i++)
|
|
{
|
|
sheet.Cell(1, i + 1).Value = headings[i];
|
|
}
|
|
|
|
sheet.SheetView.Freeze(1, 2);
|
|
sheet.SetAutoFilter(true);
|
|
sheet.Cells("A1:ZZ1").Style.Font.Bold = true;
|
|
}
|
|
|
|
foreach (var document in documents.Where(x => x.DocumentType == documentType.name).OrderBy(x => x.Correspondent))
|
|
{
|
|
var rowColour = XLColor.Transparent;
|
|
var expirationDate = document.CustomFields.FirstOrDefault(x => x.Name.Contains("expir", StringComparison.OrdinalIgnoreCase))?.DateValue;
|
|
|
|
if (expirationDate != null && expirationDate <= DateTime.Today)
|
|
{
|
|
rowColour = XLColor.Red;
|
|
}
|
|
else if (expirationDate != null && expirationDate?.AddDays(-30) < DateTime.Today)
|
|
{
|
|
rowColour = XLColor.Orange;
|
|
}
|
|
|
|
if(sheet.TabColor == XLColor.Green
|
|
&& rowColour != XLColor.Transparent)
|
|
{
|
|
sheet.TabColor = sheet.TabColor == XLColor.Red ? XLColor.Red : rowColour;
|
|
}
|
|
|
|
var rowIndex = sheet.LastRowUsed()?.RowNumber() + 1 ?? 2;
|
|
sheet.Cell(rowIndex, 1).Value = document.Correspondent;
|
|
sheet.Cell(rowIndex, 2).Value = document.CustomFields.FirstOrDefault(x=>x.Name == "Role")?.StringValue;
|
|
sheet.Cell(rowIndex, 3).Value = document.CustomFields.FirstOrDefault(x => x.Name == "Specialty")?.StringValue;
|
|
sheet.Cell(rowIndex, 4).Value = document.DocumentType;
|
|
sheet.Cell(rowIndex, 5).Value = expirationDate == null ? Blank.Value : expirationDate;
|
|
sheet.Cell(rowIndex, 5).Style.Fill.BackgroundColor = rowColour == XLColor.Transparent ? sheet.Cell(rowIndex, 5).Style.Fill.BackgroundColor : rowColour;
|
|
sheet.Cell(rowIndex, 6).Value = String.Concat(document.Tags.Select(x=>x.name + ' ').ToArray()).Trim();
|
|
}
|
|
|
|
sheet.Columns().AdjustToContents();
|
|
}
|
|
}
|
|
|
|
public static void PopulateSummaryWorksheet(
|
|
IEnumerable<DocumentType> documentTypes,
|
|
IEnumerable<Tag> tags,
|
|
IEnumerable<CustomField> customFields,
|
|
IEnumerable<DocumentParsed> docs,
|
|
XLWorkbook workbook,
|
|
bool onlyCurrentDocuments = true)
|
|
{
|
|
var headers = new string[]
|
|
{
|
|
"Correspondent",
|
|
"Role (Specialty)",
|
|
"Professional Registration",
|
|
"Liability Insurance",
|
|
"ACLS",
|
|
"BLS",
|
|
"PALS",
|
|
"Vaccination Record",
|
|
"CV / Resumé",
|
|
"Misc Certificate",
|
|
"Credentialing / Privileges",
|
|
"Reference Letter"
|
|
};
|
|
|
|
var documents = docs.Where(x =>
|
|
{
|
|
if (!x.CustomFields.Any(xx => xx.Name.Contains("expir", StringComparison.OrdinalIgnoreCase)))
|
|
return true;
|
|
|
|
return onlyCurrentDocuments ? !x.Tags.Any(xx => xx.name.Contains("renewed", StringComparison.OrdinalIgnoreCase)) : true;
|
|
}).ToList();
|
|
|
|
var summarySheet = workbook.Worksheets.Add("Summary");
|
|
summarySheet.SheetView.Freeze(1, 2); //Freeze header row and, correspondent and role columns
|
|
for (int i = 1; i <= headers.Length; i++)
|
|
{
|
|
summarySheet.Cell(1, i).Value = headers[i - 1];
|
|
}
|
|
summarySheet.Cells("A1:ZZ1").Style.Font.Bold = true;
|
|
summarySheet.SetAutoFilter();
|
|
|
|
var row = 2;
|
|
foreach (var correspondent in documents.Select(x => x.Correspondent).Distinct())
|
|
{
|
|
summarySheet.Cell(row, 1).Value = correspondent;
|
|
|
|
foreach (var doc in documents.Where(x => x.Correspondent == correspondent))
|
|
{
|
|
if (summarySheet.Cell(row, 2).Value.Type == XLDataType.Blank)
|
|
{
|
|
var role = doc.CustomFields.FirstOrDefault(x => x.Name == "Role")?.Value?.ToString() ?? "";
|
|
var specialty = doc.CustomFields.FirstOrDefault(x => x.Name == "Specialty")?.Value?.ToString() ?? "";
|
|
role = $"{role} {(!string.IsNullOrWhiteSpace(specialty) ? $"({specialty})" : "")}".Trim();
|
|
summarySheet.Cell(row, 2).Value = role;
|
|
}
|
|
|
|
if (headers.IndexOf(doc.DocumentType.ToString()) + 1 is int column && column > 0)
|
|
{
|
|
XLCellValue cellValue = summarySheet.Cell(row, column).Value;
|
|
|
|
if (!cellValue.IsBlank)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (doc.DocumentType == "Reference Letter")
|
|
{
|
|
cellValue = documents.Where(x => x.Correspondent == correspondent && x.DocumentType == "Reference Letter").Count();
|
|
;
|
|
}
|
|
else if (doc.CustomFields.FirstOrDefault(x => x.Name == "Expiration Date") is CustomFieldParsed customFieldParsed &&
|
|
customFieldParsed.DateValue > DateTime.MinValue && customFieldParsed.DateValue < DateTime.MaxValue)
|
|
{
|
|
cellValue = XLCellValue.FromObject(customFieldParsed.DateValue);
|
|
}
|
|
else if (!doc.CustomFields.Any(x => x.Name == "Expiration Date"))
|
|
{
|
|
cellValue = "Present";
|
|
}
|
|
|
|
summarySheet.Cell(row, column).Value = cellValue;
|
|
}
|
|
}
|
|
|
|
row++;
|
|
}
|
|
|
|
summarySheet.Columns().AdjustToContents();
|
|
}
|
|
|
|
public static async Task<XLWorkbook> GetSummaryAsXLWorkbookAsync()
|
|
{
|
|
var documenttypes = await api.getDocumentTypesAsync();
|
|
var tags = await api.getTagsAsync();
|
|
var customFields = await api.getCustomFieldsAsync();
|
|
var documents = (await api.getMergedDocumentMetadataAsync(false, true)).Where(x => !x.CustomFields.Any(xx => xx.Name == "Action:Renewed")).OrderBy(x => x.Correspondent).ToList();
|
|
var workbook = new XLWorkbook();
|
|
|
|
PopulateSummaryWorksheet(documenttypes, tags, customFields, documents, workbook, true);
|
|
PopulateDocumentTypeWorksheets(documenttypes, tags, customFields, documents, workbook, true);
|
|
return workbook;
|
|
}
|
|
}
|
|
}
|