To create an spreadsheet document in OPEN XML and and add an TABLE to it - spreadsheet

I am trying to create an spread sheet by open xml with an table. But while opening the created excel file always it returns the error "Excel found unreadable content in test1.xlsx, do u want to recover. Why this error always happens? When the excel is created without table, i didnt get any error. Please find the below sample code which i used to create.
using (SpreadsheetDocument spreadsheetdocument = SpreadsheetDocument.Create(#"c://test.xlsx", SpreadsheetDocumentType.Workbook))
{
// add a workbookpart to the document.
WorkbookPart workbookpart = spreadsheetdocument.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
// add a worksheetpart to the workbookpart.
WorksheetPart worksheetpart = workbookpart.AddNewPart<WorksheetPart>();
worksheetpart.Worksheet = new Worksheet(new SheetData());
// add sheets to the workbook.
Sheets sheets = spreadsheetdocument.WorkbookPart.Workbook.
AppendChild<Sheets>(new Sheets());
// append a new worksheet and associate it with the workbook.
Sheet sheet = new Sheet()
{
Id = spreadsheetdocument.WorkbookPart.
GetIdOfPart(worksheetpart),
SheetId = 1,
Name = "mysheet"
};
sheets.Append(sheet);
TableDefinitionPart tableDefinitionPart = worksheetpart.AddNewPart<TableDefinitionPart>("rId1");
GenerateTablePartContent(ref tableDefinitionPart);
TableParts tableParts1 = new TableParts() { Count = (UInt32Value)2U };
TablePart tablePart1 = new TablePart() { Id = "rId1" };
tableParts1.Append(tablePart1);
worksheetpart.Worksheet.Append(tableParts1);
spreadsheetdocument.Close();
}
//Added spaces to get the code in one block
private void GenerateTablePartContent(TableDefinitionPart part)
{
Table table1 = new Table() { Id = (UInt32Value)1U, Name = "Table1", DisplayName = "Table1", Reference = "A1:C3", TotalsRowShown = false };
AutoFilter autoFilter1 = new AutoFilter() { Reference = "A1:C3" };
TableColumns tableColumns1 = new TableColumns() { Count = (UInt32Value)3U };
TableColumn tableColumn1 = new TableColumn() { Id = (UInt32Value)1U, Name = "Column1" };
TableColumn tableColumn2 = new TableColumn() { Id = (UInt32Value)2U, Name = "Column2" };
TableColumn tableColumn3 = new TableColumn() { Id = (UInt32Value)3U, Name = "Column3" };
tableColumns1.Append(tableColumn1);
tableColumns1.Append(tableColumn2);
tableColumns1.Append(tableColumn3);
TableStyleInfo tableStyleInfo1 = new TableStyleInfo() { Name = "TableStyleMedium2", ShowFirstColumn = false, ShowLastColumn = false, ShowRowStripes = true, ShowColumnStripes = false };
table1.Append(autoFilter1);
table1.Append(tableColumns1);
table1.Append(tableStyleInfo1);
part.Table = table1;
}

use Open XML SDK Productivity Tool for it. Create an excel file using normal way and put same data there as well and compare that file with the file you are creating with your code. You will see the changes there. I am also facing same issue and I am trying to fix the changes using that tool. Lets see....
and If you have solved the issue please guide me how to do it.

Related

Automatically update my Gsheet with an SQL data base

I need to update a file automatically that already has data in it.
The document is filled with an SQL data base thanks to the code below
However, I want it to update itself everyday without deleting any data that are already in the document and only adding new ones (don't want any duplicates).
function readData(db, queryString) {
//connect to the database
var server = 'your-servername-OR-serverPublicIpAddress';
var username = 'your-sql-username';
var password = 'your-password';
var dbUrl = 'jdbc:sqlserver://' + server + ':1433;databaseName=' + db;
var conn = Jdbc.getConnection(dbUrl, username, password );
//query the data
var stmt = conn.createStatement();
var exec_query = stmt.executeQuery(queryString);
var metaData = exec_query.getMetaData();
var numCols = metaData.getColumnCount();
//save query data to an array
var result=[]; //initiate a blank array
//save the column header
header = []; //initiate the header row
for (var col = 0; col < numCols; col++) {
header.push(metaData.getColumnName(col + 1)); //add the name of each column to the header row
};
result.push(header);//after the header row is formed, put it to the result array
//save the data of each row
while (exec_query.next()) {
row_data = [];
for (var col = 0; col < numCols; col++) {
row_data.push(exec_query.getString(col + 1));//add data of each column to the row data
//Logger.log(row_data);
};
result.push(row_data); // add row data to result
//Logger.log(result);
};
exec_query.close();
return result
};
function pushDataToGoogleSheet(data, SheetName) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName(SheetName));
var lastRow = sheet.getLastRow();
sheet.getRange(lastRow+1, 1, data.length, data[0].length).setValues(data);
sheet.getDataRange().removeDuplicates();
};
function main() {
db = 'YOUR_DATABASE_NAME'
SQLquery = 'YOUR_SQL_QUERY'
raw_statistics = readData(db, SQLquery); //get raw statistics
pushDataToGoogleSheet(raw_statistics, 'YOUR_SHEET_NAME'); //push to google sheet
};
function main() {
db = 'YOUR_DATABASE_NAME'
SQLquery = 'YOUR_SQL_QUERY'
raw_statistics = readData(db, SQLquery); //get raw statistics
pushDataToGoogleSheet(raw_statistics, 'YOUR_SHEET_NAME'); //push to google sheet
};
However, in the pushDataToGoogleSheet it says that it can't define the length. So, I don't know if I put the right thing for data or not or if there is an issue in my code...
Do you have an idea ?
Thank you for your help !

Is it possible to create dynamic charts in epplus?

I am wondering if it is possible to configure epplus in such a way that when the excel file is opened the table data can be clicked on and a graph will be displayed based on the row of the table clicked. (I realize this is super easy to do in excel I would just rather have everything taken care of before it gets to certain people)
Currently I just have one data table and a graph for each row but it would be better if there was just one graph that changed based on what row is clicked in excel. I also tried a pivot table but that doesn't help me with the dynamic chart.
For anyone trying to figure this out as well. I ended up using a data validation drop down list and making a dynamic table row (outside the base table) that the dynamic chart is based on. The dynamic table row changes based on the value of the data validation dropdown list (you kinda need a feel for excel to be able to do this which I didn't have):
class Program
{
static void Main(string[] args)
{
// Creating an instance
// of ExcelPackage
ExcelPackage excel = new ExcelPackage();
// name of the sheet
var workSheet = excel.Workbook.Worksheets.Add("testSheet");
//init table
var randTable = new DataTable();
randTable.TableName = "randTable";
//init columns
var countColumn = new DataColumn()
{
DataType = typeof(int),
ColumnName = "Count",
ReadOnly = true,
Unique = true
};
var randomColumn0 = new DataColumn()
{
DataType = typeof(int),
ColumnName = "Random-0",
ReadOnly = true,
Unique = false
};
var randomColumn1 = new DataColumn()
{
DataType = typeof(int),
ColumnName = "Random-1",
ReadOnly = true,
Unique = false
};
//add columns to table
randTable.Columns.AddRange(new DataColumn[] { countColumn, randomColumn0, randomColumn1 });
//init data validation
ExcelRange dropdownRange = workSheet.Cells[12, 1, 12, 3];
var dropdownValidation = workSheet.DataValidations.AddListValidation(dropdownRange.Address);
workSheet.Names.Add("count", dropdownRange);
//style data validation
dropdownRange.Merge = true;
workSheet.Cells[dropdownRange.Address].Style.Fill.PatternType = ExcelFillStyle.Solid;
workSheet.Cells[dropdownRange.Address].Style.Fill.BackgroundColor.SetColor(Color.Yellow);
workSheet.Cells[dropdownRange.Address].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
var rand = new Random();
for (var i = 0; i < 10; i++)
{
//add table first column values to validation list
dropdownValidation.Formula.Values.Add(i.ToString());
var row = randTable.NewRow();
row[countColumn] = i;
row[randomColumn0] = rand.Next(0, 100);
row[randomColumn1] = rand.Next(0, 100);
randTable.Rows.Add(row);
}
//make the tableIndexer cell. This cell will be used to get the
//table indices for the selected table row cells
ExcelRange randTableIndexer = workSheet.Cells[12, 4, 12, 4];
randTableIndexer.Formula = "MATCH(INDEX(count,1,1), randTable[Count], 0)";
workSheet.Cells[randTableIndexer.Address].Style.Fill.PatternType = ExcelFillStyle.Solid;
workSheet.Cells[randTableIndexer.Address].Style.Fill.BackgroundColor.SetColor(Color.LightGreen);
workSheet.Cells[randTableIndexer.Address].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
workSheet.Names.Add("tableIndex", randTableIndexer);
//make the cells based off the table at row(randTableIndexer.value)
ExcelRange graphCells = workSheet.Cells[13, 1, 13, 3];
graphCells.CreateArrayFormula("INDEX(randTable[], tableIndex, 0)"); //need [] on table names in epplus formulas
workSheet.Cells[graphCells.Address].Style.Fill.PatternType = ExcelFillStyle.Solid;
workSheet.Cells[graphCells.Address].Style.Fill.BackgroundColor.SetColor(Color.LightBlue);
workSheet.Cells[graphCells.Address].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
graphCells.Calculate();
//add table to workSheet
workSheet.Cells[1, 1].LoadFromDataTable(randTable, true, OfficeOpenXml.Table.TableStyles.Medium15);
workSheet.Cells.AutoFitColumns();
//add dynamic chart
var chart = workSheet.Drawings.AddChart("rands", eChartType.Pie) as ExcelPieChart;
chart.Title.Text = "rands";
chart.Series.Add(graphCells.Address, ExcelRange.GetAddress(1, 1, 3, 1));
chart.Legend.Position = eLegendPosition.Bottom;
chart.SetSize(500, 400);
chart.SetPosition(60, 500);
WriteToFile(excel);
}
public static void WriteToFile(ExcelPackage package)
{
// file name with .xlsx extension
string p_strPath = "C:\\your\\file\\path";
if (File.Exists(p_strPath))
File.Delete(p_strPath);
// Create excel file on physical disk
FileStream objFileStrm = File.Create(p_strPath);
objFileStrm.Close();
// Write content to excel file
File.WriteAllBytes(p_strPath, package.GetAsByteArray());
}
}

NullReference Error while reading xlsx EPPlus Core

I'm trying to upload an excel file with EPPlus. I'ts like my excel file was empty, but it has content inside.
Im getting this error:
worksheet.Dimension.Rows = 'worksheet.Dimension.Rows' threw an exception of type 'System.NullReferenceException'
on this line: int rowCount = worksheet.Dimension.Rows;
[HttpPost("Excel")]
public string UploadExcel(IFormFile file)
{
var filePath = Path.GetTempFileName();
FileInfo excel = new FileInfo(filePath);
using (ExcelPackage package = new ExcelPackage(excel))
{
StringBuilder sb = new StringBuilder();
ExcelWorksheet worksheet = package.Workbook.Worksheets[file.FileName];
int rowCount = worksheet.Dimension.Rows;
int ColCount = worksheet.Dimension.Columns;
bool bHeaderRow = true;
for (int row = 1; row <= rowCount; row++)
{
for (int col = 1; col <= ColCount; col++)
{
if (bHeaderRow)
{
sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
}
else
{
sb.Append(worksheet.Cells[row, col].Value.ToString() + "\t");
}
}
sb.Append(Environment.NewLine);
}
return sb.ToString();
}
Can you verify that the workshseets are being loaded?
//examine in the debugger to make sure the worksheet you want is loaded
var worksheets = package.Workbook.Worksheets.ToList();
If that doesn't work, can you try one of these?
var worksheet = package.Workbook.Worksheets[0];
var worksheetFirst = package.Workbook.Worksheets.First();
UPDATE:
The real error is that you are trying to read a temp file with var filePath = Path.GetTempFileName();. You need to read an actual excel file. For example, you could use Path.GetFullPath("path/to/the/excel/file.xls");

Trying to create multiple PDF for each row in a Google Sheet

I am trying to create a separate PDF for each row in a Google Sheet using a Google Doc as a template. I can get it to work when I use the active row; however, when I try to loop the createpdf function the only PDF I am left with is the last row. My thoughts are that I am deleting all of the files beforehand but I can't figure out where the error is. Any help would be awesome.
var TEMPLATE_ID = '1Mxrm0kny8R7ROlBou8kSUc8dOvvH8PvtQ-EC_Nd3FUQ';
function onOpen() {
SpreadsheetApp
.getUi()
.createMenu('Create PDF')
.addItem('Create PDF', 'createPdf')
.addToUi();
}
for (var i=2; i < 3; i++) { function createPdf() {
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs');
return;
}
// Set up the docs and the spreadsheet access
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId),
copyBody = copyDoc.getBody(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRow = activeSheet.getRange(i, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0,
fileName = activeRow[0][0] + activeRow[0][1],
pdfFile,
pdfFile2;
// Replace the keys with the spreadsheet values
for (;columnIndex < headerRow[0].length; columnIndex++) {
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%',
activeRow[0][columnIndex]);
}
// Create the PDF file and delete the doc copy
copyDoc.saveAndClose();
pdfFile = DriveApp.createFile(copyFile.getAs("application/pdf"));
pdfFile2 = pdfFile.setName(fileName)
copyFile.setTrashed(true);
return pdfFile2;
}}
Tip: pay attention to formatting your code properly, because it will help you understand its structure. Here's what you have after passing it through jsbeautifier:
var TEMPLATE_ID = '1Mxrm0kny8R7ROlBou8kSUc8dOvvH8PvtQ-EC_Nd3FUQ';
function onOpen() {
SpreadsheetApp
.getUi()
.createMenu('Create PDF')
.addItem('Create PDF', 'createPdf')
.addToUi();
}
for (var i = 2; i < 3; i++) {
function createPdf() {
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs');
return;
}
// Set up the docs and the spreadsheet access
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId),
copyBody = copyDoc.getBody(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRow = activeSheet.getRange(i, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0,
fileName = activeRow[0][0] + activeRow[0][1],
pdfFile,
pdfFile2;
// Replace the keys with the spreadsheet values
for (; columnIndex < headerRow[0].length; columnIndex++) {
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%',
activeRow[0][columnIndex]);
}
// Create the PDF file and delete the doc copy
copyDoc.saveAndClose();
pdfFile = DriveApp.createFile(copyFile.getAs("application/pdf"));
pdfFile2 = pdfFile.setName(fileName)
copyFile.setTrashed(true);
return pdfFile2;
}
}
The indenting clarifies a few problems:
The for loop on i is in global scope, not part of any function. It will therefore execute every time ANY function in the script is invoked, but is not explicitly invocable, as it would be in a function.
The function createPDF is declared inside that for loop. This is in global scope (see point 1), so it's still available to be called from other functions such as the menu created by your onOpen(). HOWEVER, because it's just a declaration, it is NOT invoked by the i loop! (This was the primary concern of your question.)
There's a return call inside createPdf() that is probably a left-over from the original copy of this code which produced a single PDF. Because it returns in the first time through the loop, it will STILL make a single PDF. That line needs to be moved or deleted.
return pdfFile2;
Flipping those couple of lines and deleting the return should sort us out.
var TEMPLATE_ID = '1Mxrm0kny8R7ROlBou8kSUc8dOvvH8PvtQ-EC_Nd3FUQ';
function onOpen() {
SpreadsheetApp
.getUi()
.createMenu('Create PDF')
.addItem('Create PDF', 'createPdf')
.addToUi();
}
function createPdf() {
for (var i = 2; i < 3; i++) {
if (TEMPLATE_ID === '') {
SpreadsheetApp.getUi().alert('TEMPLATE_ID needs to be defined in code.gs');
return;
}
// Set up the docs and the spreadsheet access
var copyFile = DriveApp.getFileById(TEMPLATE_ID).makeCopy(),
copyId = copyFile.getId(),
copyDoc = DocumentApp.openById(copyId),
copyBody = copyDoc.getBody(),
activeSheet = SpreadsheetApp.getActiveSheet(),
numberOfColumns = activeSheet.getLastColumn(),
activeRow = activeSheet.getRange(i, 1, 1, numberOfColumns).getValues(),
headerRow = activeSheet.getRange(1, 1, 1, numberOfColumns).getValues(),
columnIndex = 0,
fileName = activeRow[0][0] + activeRow[0][1],
pdfFile,
pdfFile2;
// Replace the keys with the spreadsheet values
for (; columnIndex < headerRow[0].length; columnIndex++) {
copyBody.replaceText('%' + headerRow[0][columnIndex] + '%',
activeRow[0][columnIndex]);
}
// Create the PDF file and delete the doc copy
copyDoc.saveAndClose();
pdfFile = DriveApp.createFile(copyFile.getAs("application/pdf"));
pdfFile2 = pdfFile.setName(fileName)
copyFile.setTrashed(true);
}
}

LINQ how to generate csv file section

I got the problem generating csv file based on the section. I currently using LinqToCsv dll to generate the file. How do I generate the file by section. Please help. Thanks.
Currenly I have 3 section
Header Section
Detail Section
Footer Section
Here my codes.
TTMSEntities DB = new TTMSEntities();
CsvFileDescription outputFileDescription = new CsvFileDescription();
outputFileDescription.NoSeparatorChar = false;
outputFileDescription.FirstLineHasColumnNames = true;
outputFileDescription.FileCultureName = "en-US";
List<HeaderRec> list1 = new List<HeaderRec>();
HeaderRec header = new HeaderRec();
header.RecordType = "";
header.RetailerID = "";
header.FileDate = "";
header.FileSequence = "";
header.LastTransRef = "";
list1.Add(header);
var Data = (from p in DB.TT_TNG_KFC_TRANSACTION_UPLOAD
select new DetailRec
{
RecordType = "D",
TransIDType ="AA"
});
List<FooterRec> list2 = new List<FooterRec>();
FooterRec footer = new FooterRec();
footer.RecordType = "T";
footer.TotalAmount = "100";
list2.Add(footer);
CsvContext cc = new CsvContext();
cc.Write(Data, "TestData.csv", outputFileDescription);
How to I concat the List ?