Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Excel.cs #14066

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
367 changes: 367 additions & 0 deletions src/Libraries/DSOffice/Excel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,373 @@ public static object[][] WriteToFile(string filePath, string sheetName, int star
}
}

[IsVisibleInDynamoLibrary(false)]
public class WorkSheet
{
#region Helper methods

private static object[][] ConvertToJaggedArray(object[,] input, bool convertToString = false)
{
int rows = input.GetUpperBound(0);
int cols = input.GetUpperBound(1);

object[][] output = new object[rows][];

for (int i = 0; i < rows; i++)
{
output[i] = new object[cols];

for (int j = 0; j < cols; j++)
{
if (convertToString)
{
if (input[i + 1, j + 1] == null)
output[i][j] = null;
else
output[i][j] = input[i + 1, j + 1].ToString();
}
else
output[i][j] = input[i + 1, j + 1];
}
}

return output;
}

private static object[,] ConvertToDimensionalArray(object[][] input, out int rows, out int cols)
{
if (input == null)
{
rows = cols = 1;
return new object[,] { { "" } };
}

rows = input.GetUpperBound(0) + 1;
cols = 0;
for (int i = 0; i < rows; i++)
{
if (input[i] != null)
cols = Math.Max(cols, input[i].GetUpperBound(0) + 1);
}

// if the input data is an empty list or a list of nested empty lists
// return an empty cell
if(rows == 0 || cols == 0)
{
rows = cols = 1;
return new object[,] { { "" } };
}

object[,] output = new object[rows, cols];

for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (input[i] == null || j > input[i].GetUpperBound(0))
output[i, j] = "";
else
{
var item = input[i][j];

if (item is double)
{
output[i, j] = ((double)item).ToString(CultureInfo.InvariantCulture);
}
else if (item is float)
{
output[i, j] = ((float)item).ToString(CultureInfo.InvariantCulture);
}
else if (item is DateTime)
{
output[i, j] = ((DateTime)item).ToString(CultureInfo.InvariantCulture);
}
else if (item == null)
{
output[i, j] = "";
}
else if (item is StackValue)
{
if (((StackValue)item).IsPointer)
{
string message = string.Format(Properties.Resources.kMethodResolutionFailureWithTypes,
"Excel.WriteToFile", "Function");
LogWarningMessageEvents.OnLogWarningMessage(message);
return null;
}

output[i, j] = item.ToString();
}
else
{
output[i, j] = item.ToString();
}
}

}
}

return output;
}

#endregion
/// <summary>
/// Returns data from given worksheet (GetDataFromExcelWorksheet node)
/// </summary>
internal object[][] Data
{
get
{
return GetData();
}
}

internal object[][] GetData(bool convertToString = false)
{
var vals = ws.UsedRange.get_Value();

// if worksheet is empty
if (vals == null)
return new object[0][];

// if worksheet contains a single value
if (!vals.GetType().IsArray)
return new object[][] { new object[] { vals } };

return ConvertToJaggedArray((object[,])vals, convertToString);
}

private WorkBook wb = null;
private Worksheet ws = null;

/// <summary>
/// create new worksheet from given workbook and name (AddExcelWorksheetToWorkbook node)
/// </summary>
/// <param name="wbook"></param>
/// <param name="sheetName"></param>
/// <param name="overWrite"></param>
internal WorkSheet(WorkBook wbook, string sheetName, bool overWrite = false)
{
wb = wbook;

// Look for an existing worksheet
WorkSheet[] worksheets = wbook.WorkSheets;
WorkSheet wSheet = worksheets.FirstOrDefault(n => n.ws.Name == sheetName);

if (wSheet == null)
{
// If you don't find one, create one.
ws = (Worksheet) wb.Add();
ws.Name = sheetName;
wb.Save();
return;
}

// If you find one, then use it.
if (overWrite)
{
// if there is only one worksheet, we need to add one more
// before we can delete the first one
ExcelInterop.App.DisplayAlerts = false;
ws = (Worksheet) wb.Add();
wSheet.ws.Delete();
ws.Name = sheetName;
wb.Save();
ExcelInterop.App.DisplayAlerts = true;

}
else
ws = wSheet.ws;
}

internal WorkSheet(Worksheet ws, WorkBook wb)
{
this.ws = ws;
this.wb = wb;
}

/// <summary>
/// instance method, write data to existing worksheet, (WriteDataToExcelWorksheet node)
/// </summary>
/// <param name="startRow"></param>
/// <param name="startColumn"></param>
/// <param name="data"></param>
/// <param name="writeAsString"></param>
/// <returns></returns>
internal WorkSheet WriteData(int startRow, int startColumn, object[][] data, bool writeAsString = false)
{
startRow = Math.Max(0, startRow);
startColumn = Math.Max(0, startColumn);
int numRows, numColumns;

object[,] rangeData = ConvertToDimensionalArray(data, out numRows, out numColumns);

if (rangeData == null)
return this;

var c1 = (Range)ws.Cells[startRow + 1, startColumn + 1];
var c2 = (Range)ws.Cells[startRow + numRows, startColumn + numColumns];
var range = ws.Range[c1, c2];
if(writeAsString)
range.NumberFormat = "@";
range.Value = rangeData;

wb.Save();
return this;
}

}

[IsVisibleInDynamoLibrary(false)]
public class WorkBook
{
/// <summary>
///
/// </summary>
internal string Name { get; set; }

/// <summary>
/// (GetWorksheetsFromExcelWorkbook node)
/// </summary>
internal WorkSheet[] WorkSheets
{
get
{
return wb.Worksheets.Cast<Worksheet>().Select(n => new WorkSheet(n, this)).ToArray();
}
}

private Workbook wb = null;

internal object Add()
{
return wb.Worksheets.Add();
}

internal void Save()
{
if (!String.IsNullOrEmpty(wb.Path))
wb.Save();
}

/// <summary>
/// Creates a new Workbook with filepath and sheet name as input
/// </summary>
internal WorkBook(string filePath)
{
Name = filePath;

if (!String.IsNullOrEmpty(filePath))
{
try
{
// Look for an existing open workbook
var workbookOpen = ExcelInterop.App.Workbooks.Cast<Workbook>()
.FirstOrDefault(e => e.FullName == filePath);

// Use the existing workbook.
if (workbookOpen != null)
{
wb = workbookOpen;
}
// If you can't find an existing workbook at
// the specified path, then create a new one.
else
{
Workbook workbook = ExcelInterop.App.Workbooks.Open(filePath);
wb = workbook;
wb.Save();
}
}
catch (Exception)
{
// Exception is thrown when there is no existing workbook with the given filepath
wb = ExcelInterop.App.Workbooks.Add();
wb.SaveAs(filePath);
}
}
else
wb = ExcelInterop.App.Workbooks.Add();
}

/// <summary>
/// Helper method for reading workbooks with a disabled visibility.
/// </summary>
internal void CloseHidden()
{
wb.Close();
wb = null;
}

/// <summary>
/// (SaveAsExcelWorkbook node)
/// </summary>
/// <param name="wbook"></param>
/// <param name="filename"></param>
internal WorkBook(WorkBook wbook, string filename)
{
Name = filename;
wb = wbook.wb;

if (wb.FullName == filename)
wb.Save();
else
{
try
{
Workbook workbook = ExcelInterop.App.Workbooks.Open(filename);
workbook.Close(false);
}
catch (Exception)
{
}

wb.SaveAs(filename);
}

}

private WorkBook(Workbook wb, string filePath)
{
this.wb = wb;
Name = filePath;
}

/// <summary>
/// (ReadExcelFile node)
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
internal static WorkBook ReadExcelFile(string path)
{
var workbookOpen = ExcelInterop.App.Workbooks.Cast<Workbook>()
.FirstOrDefault(e => e.FullName == path);

if (workbookOpen != null)
return new WorkBook(workbookOpen, path);

if (File.Exists(path))
return new WorkBook(ExcelInterop.App.Workbooks.Open(path, true, false), path);

throw new FileNotFoundException("File path not found.", path);
}

/// <summary>
/// instance method, (GetExcelWorksheetByName node)
/// </summary>
/// <param name="sheetName"></param>
/// <returns></returns>
internal WorkSheet GetWorksheetByName(string sheetName)
{
var ws = wb.Worksheets.Cast<Worksheet>().FirstOrDefault(sheet => sheet.Name == sheetName);

if (ws == null)
throw new ArgumentException(string.Format(Properties.Resources.WorksheetNotFound, sheetName));

return new WorkSheet(ws, this);
}

}
/// <summary>
/// Methods for Import/Export category.
/// </summary>
Expand Down