/// Copyright (c) 2021 Iiro Iivanainen, Harri Linna, Jere Pakkanen, Riikka Vilavaara /// /// Permission is hereby granted, free of charge, to any person obtaining /// a copy of this software and associated documentation files (the /// "Software"), to deal in the Software without restriction, including /// without limitation the rights to use, copy, modify, merge, publish, /// distribute, sublicense, and/or sell copies of the Software, and to /// permit persons to whom the Software is furnished to do so, subject to /// the following conditions: /// /// The above copyright notice and this permission notice shall be included /// in all copies or substantial portions of the Software. /// /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, /// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF /// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. /// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY /// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, /// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE /// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /// using ExcelDataReader; using System; using System.IO; using System.Reflection; namespace GroundhogApp { /// /// Common static methods for GUI. /// class Utilities { /// /// Formats raw byte amounts to appropriate unit (B, KB, MB, GB or TB). /// /// The number of bytes /// Bytes formatted to appropriate unit public static string FormatBytes(long bytes) { string[] units = { "B", "KB", "MB", "GB", "TB" }; double amountOf = bytes; int i; for (i = 0; i < units.Length && bytes >= 1024; i++, bytes /= 1024) { amountOf = bytes / 1024.0; } return String.Format("{0:0.00} {1}", amountOf, units[i]); } /// /// Returns sortable DateTime with universal time coordinate value. /// /// Datetime public static string GetDateTime() { return DateTime.Now.ToString("yyyy-MM-dd HH:mm:sszzz"); } /// /// Retrieves the username from the Windows environment. /// /// Username of the Windows environment public static string GetEnvironmentUser() { return Environment.UserName; } /// /// Copies the specified file to specified destination location. /// If the file already exists in target destination then just /// returns the file destination of the file. /// /// File to be copied /// Created if the folder doesn't already exist /// The app folder if not specified /// The destination of the new file public static string CopyToFolder(string filePath, string folderName, string copyPath) { string completeFolder = Path.Combine(copyPath, folderName); Directory.CreateDirectory(completeFolder); FileInfo fileInfo = new(filePath); string newFile = completeFolder + "\\" + fileInfo.Name; try { File.Copy(filePath, newFile); } catch (IOException) { // File already exists, no need to copy. } return newFile; } /// /// Attempts to select the specified file from the explorer. /// /// Requested file's path /// Did the specified file exist public static bool OpenFolderFileSelected(string filePath) { if (File.Exists(filePath)) { string fullPath = Path.GetFullPath(filePath); System.Diagnostics.Process.Start("explorer.exe", string.Format("/select,\"{0}\"", fullPath)); return true; } return false; } /// /// Attempts to open the folder of the file specified in explorer. /// /// Requested file's path /// Did the specified folder exist public static bool OpenFolder(string filePath) { string folderPath = Path.GetDirectoryName(filePath); if (Directory.Exists(folderPath)) { System.Diagnostics.Process.Start("explorer.exe", folderPath); return true; } return false; } /// /// Attempts to open the file specified. /// /// Requested file's path /// Did the specified file exist public static bool OpenFile(string filePath) { if (File.Exists(filePath)) { System.Diagnostics.Process.Start("explorer.exe", filePath); return true; } return false; } /// /// Attempts to open the file from the application location. /// /// Requested file's path /// Did the specified file exist public static bool OpenFileAssembly(string filePath) { string completepath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @filePath); if (File.Exists(completepath)) { System.Diagnostics.Process.Start("explorer.exe", completepath); return true; } return false; } /// /// Reads a .csv file to a jagged array ("array of arrays"). /// /// Requested file's path /// Array of the .csv values public static string[,] ReadCSVToMatrix(string filePath, char deselector = '\0') { System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); char[] candidates; if (deselector == '\0') candidates = new char[] { ',', ';', '\t', '|', '#', ' ' }; else candidates = new char[] { deselector }; var conf = new ExcelReaderConfiguration(); conf.AutodetectSeparators = candidates; string[,] matrix; using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using var reader = ExcelReaderFactory.CreateCsvReader(stream, conf); do { matrix = new string[reader.RowCount, reader.FieldCount]; for (int r = 0; r < reader.RowCount; r++) { reader.Read(); for (int c = 0; c < reader.FieldCount; c++) { string value = reader.GetValue(c)?.ToString().Trim(); matrix[r, c] = value; } } } while (reader.NextResult()); // only one result with csv-files } return matrix; } /// /// Reads an .xls, .xlsx and .xlsb files and returns an array of two dimensional arrays /// representing the workbook. /// /// Requested file's path /// Jagged array where inner arrays represent workbook sheets public static string[][,] ReadExcel(string filePath) { // Required step for using ExcelReader with .NET Core System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); string[][,] workbook; using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { // Auto-detect format, supports: // - Binary Excel files (2.0-2003 format; *.xls) // - OpenXml Excel files (2007 format; *.xlsx, *.xlsb) using var reader = ExcelReaderFactory.CreateReader(stream); workbook = new string[reader.ResultsCount][,]; int s = 0; do { string[,] sheet = new string[reader.RowCount, reader.FieldCount]; for (int r = 0; r < reader.RowCount; r++) { reader.Read(); for (int c = 0; c < reader.FieldCount; c++) { string value = reader.GetValue(c)?.ToString().Trim(); sheet[r, c] = value; } } workbook[s] = sheet; s++; } while (reader.NextResult()); } return workbook; } /// /// Returns the sheet names in the Excel file. /// /// Requested file's path /// Sheet names of the Excel file public static string[] GetExcelSheetNames(string filePath) { string[] sheetNames; using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using var reader = ExcelReaderFactory.CreateReader(stream); sheetNames = new string[reader.ResultsCount]; for (int i = 0; i < reader.ResultsCount; i++) { sheetNames[i] = reader.Name; reader.NextResult(); } } return sheetNames; } /// /// Makes the header appropriate for a WPF datagrid column name. /// If the header does not exist, returns specified default header. /// /// Header to be prepared /// Default value for a null header /// Prepared header public static string PrepareHeader(string header, string defaultHeader) { if (header == null) return defaultHeader; // Replace Dot with similar looking One Dot Leader header = header.Replace(".", "\x2024"); char[] badCharacters = new char[] { '(', ')', '[', ']', '/', '\\' }; foreach (char c in badCharacters) { header = header.Replace(c.ToString(), " "); } header = header.Trim(); if (header.Length == 0) return defaultHeader; return header; } } }