My code is here but i cannot get my required result
DataTable dtWB = new DataTable();
dtWB.Columns.Add("Name");
dtWB.Columns.Add("DOS");
dtWB.Columns.Add("CPT");
dtWB.AcceptChanges();
DataRow drWB = null;
// Auto-detect format, supports:
byte[] ExcelData = File.ReadAllBytes(AppDomain.CurrentDomain.BaseDirectory + path);
MemoryStream stream = new MemoryStream(ExcelData);
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
// Choose one of either 1 or 2:
// 1. Use the reader methods
do
{
while (reader.Read())
{
// reader.GetDouble(0);
}
} while (reader.NextResult());
// 2. Use the AsDataSet extension method
var result = reader.AsDataSet();
//The result of each spreadsheet is in result.Tables
var Tables = result.Tables;
var CT = Tables.Count;
DataTable WBdt = Tables[1];
}
I have a data in an excel sheet like this
https://i.stack.imgur.com/nZl4K.png
I want to show data like this using c#.
https://i.stack.imgur.com/BjzZd.png
Your "Code" simply consists of the ExcelDataReader documentation sample. This will parse the dataset into a collection with the format you requested.
var records = new Dictionary<string, Dictionary<DateTime, double?>>();
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
var firstTable = reader.AsDataSet().Tables[0];
for (int i = 1; i < firstTable.Rows.Count; i++)
{
string name = firstTable.Rows[i].Field<string>(0);
var dt_values = new Dictionary<DateTime, double?>();
for (int j = 1; j < firstTable.Columns.Count; j++)
{
DateTime dt = firstTable.Rows[0].Field<DateTime>(j);
double? value = firstTable.Rows[i].Field<double?>(j);
dt_values.Add(dt, value);
}
records.Add(name, dt_values);
}
}
}
var formatted_data = records.SelectMany(x => x.Value.Select(y => new
{
Name = x.Key,
Dos = y.Key.ToShortDateString(),
CPT = y.Value
}));
Related
I want the elements of the first column of an Excel sheet to be added to the list.
This is my code:
var list = new List<string>();
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (var package = new ExcelPackage(stream))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
var rowcount = worksheet.Dimension.Rows;
var columncount = worksheet.Dimension.Columns;
var column = worksheet.Rows[1].Range.Value;
var range = worksheet.Rows.Range.Value;
var row = worksheet.Columns[1].Range.Value;
list.Add(column.ToString());
}
}
for(int i = 1; i <= columncount; i++)
{
var field1 = worksheet.Cells[1,i].Value as string;
list.Add(field1);
field1 = null;
}
this loop will give the first column names
public void DecryptFile(string filePath, string CompanyName)
{
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
using (var gzStream = new GZipStream(fileStream, CompressionMode.Decompress))
{
using (var outputStream = new MemoryStream())
{
gzStream.CopyTo(outputStream);
byte[] outputBytes = outputStream.ToArray();
// DeserailizeByteArrayToDatatable(outputBytes, CompanyName);
string FileContents = Encoding.ASCII.GetString(outputBytes);
DataTable dt = new DataTable();
string[] arrayList = FileContents.Split("\n");
}
}
}
}
I have decrypted contents of file and now I want to fill the data to DataTable. The format of file contents is:
serial_number,peak_period_start_time,stop_time
15AA01AF361903PC,1602619200,1602615600
15AA01AF361902QB,1602619200,1602615600
15AA01AF361906YL,1602619200,1602630000
09AA01AF32190YXP,1602619200,1602630000
so I want to fil the first line as column in DataTable and rest all as rows and aslo additionally I want to change the start_time and stop time to correct format
I would suggest you to first create a method that will accept a DataTable and an array of columns and will add columns to the DataTable.
public DataTable AddColumns(DataTable dt, string[] columns)
{
if (dt == null) dt = new DataTable();
foreach (string column in columns)
{
dt.Columns.Add(column.Trim());
}
return dt;
}
Then, Create a method that will populate data into that DataTable:
public DataTable PopulateData(DataTable dt, string[] dataLines)
{
if (dataLines == null || dataLines.Length == 0) return dt;
foreach (string line in dataLines)
{
var splittedLine = line.Split(',');
var row = dt.NewRow();
for (int i = 0; i < splittedLines.Length; i++)
{
row[i] = splittedLines[i].Trim();
}
dt.Rows.Add(row);
}
return dt;
}
Call the methods above in your DecryptFile method, like below:
public void DecryptFile(string filePath, string CompanyName)
{
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
using (var gzStream = new GZipStream(fileStream, CompressionMode.Decompress))
{
using (var outputStream = new MemoryStream())
{
gzStream.CopyTo(outputStream);
byte[] outputBytes = outputStream.ToArray();
// DeserailizeByteArrayToDatatable(outputBytes, CompanyName);
string FileContents = Encoding.ASCII.GetString(outputBytes);
DataTable dt = new DataTable();
string[] arrayList = FileContents.Split("\n");
// Usage
if (arrayList.Length > 0)
{
var columns = arrayList[0].Split(',');
var data = arrayList.AsEnumerable().Skip(1).ToArray(); // skip the first line.
dt = PopulateData(AddColumns(dt, columns), data);
}
}
}
}
}
Note: I see, your file has 4 columns in header row and it is supplying 3 values which is not correct, you must supply equal columns and its values otherwise, you might want to handle the row creation differently.
The general concept I would follow would be to:
Read the first row and determine which and how many columns I need to create
For each column use f.Columns.Add() to add the column to the DataTable.
For each row following do f.Rows.Add() filling in the data.
Something like:
public void DecryptFile(string filePath, string CompanyName)
{
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
using (var gzStream = new GZipStream(fileStream, CompressionMode.Decompress))
{
using (var outputStream = new MemoryStream())
{
gzStream.CopyTo(outputStream);
byte[] outputBytes = outputStream.ToArray();
//DeserailizeByteArrayToDatatable(outputBytes, CompanyName);
string FileContents = Encoding.ASCII.GetString(outputBytes);
DataTable newTable = new DataTable();
string[] arrayList = FileContents.Split('\n');
int rowIndex = 0;
foreach (string line in arrayList)
{
// Assuming comma separated columns
string[] columns = line.Split(',');
int columnIndex = 0;
DataRow row = (rowIndex == 0 ? null : newTable.NewRow());
foreach (string columnValue in columns)
{
if (rowIndex == 0)
{
newTable.Columns.Add(new DataColumn(columnValue));
}
else
{
row[columnIndex] = columnValue;
}
}
rowIndex ++;
}
}
}
}
(have not tested the code)
You can create data table by using below function. I am not sure what format you want for start time and end time, so I have mentioned it in comments where you can do that.
public static DataTable ArrayOfStringToDataTable(string[] stringArray)
{
DataTable dataTable = new DataTable();
if (stringArray.Length == 0)
{
return dataTable;
}
var headers = stringArray[0].Split(',');
foreach (var header in headers)
{
dataTable.Columns.Add(header, typeof(string));
}
if (stringArray.Length == 1)
{
return dataTable;
}
for (var i = 1; i < stringArray.Length; i++) {
var rows = stringArray[i].Split(',');
var dataRow = dataTable.NewRow();
dataRow[0] = rows[0];
dataRow[1] = rows[1]; // do required formatting
dataRow[2] = rows[2]; // do required formatting
dataTable.Rows.Add(dataRow);
}
return dataTable;
}
I have this code here that works how I want, but I'm developing on .Net Standard and cannot use the Microsoft.VisualBasic.FileIO library. I would like to be able to do the same thing using CsvHelper
Is it possible with CsvHelper to, first get the header row as a string array. Second, get each row as a string array of items?
using Microsoft.VisualBasic.FileIO;
using (TextFieldParser csvParser = new TextFieldParser("FilePath"))
{
csvParser.CommentTokens = new string[] { "#" };
csvParser.SetDelimiters(new string[] { "," });
csvParser.HasFieldsEnclosedInQuotes = true;
csvParser.TrimWhiteSpace = true;
string[] fields = csvParser.ReadFields();
int arraySize = fields.Length;
int index = Array.IndexOf(fields, columnExtracted);
while (!csvParser.EndOfData)
{
fields = csvParser.ReadFields();
string column = fields[index];
Console.WriteLine(column);
}
}
I tried the following code that reads the cells but breaks the line when faced with a delimiter because of the line string Csv = string.Join("\n", result.ToArray());
Is there a way to put all the info in an array? It's already stored in a string list but I cannot retrieve the data by an index.
List<string> result = new List<string>();
string value;
using (TextReader fileReader = File.OpenText("FilePath"))
{
var csv = new CsvReader(fileReader, CultureInfo.InvariantCulture);
csv.Configuration.HasHeaderRecord = true;
while (csv.Read())
{
for (int i = 0; csv.TryGetField<string>(i, out value); i++)
{
result.Add(value);
}
if (csv.Read() == false)
break;
}
}
string Csv = string.Join("\n", result.ToArray());
EDIT
This is my new code now after the feedback. But, it seems that it's leaving out the header row when iterating through the List that stores all the records.
public List<string> HeaderColumnParser(string columnExtracted, string PathToFile)
{
List<string> result = new List<string>();
string value;
using (TextReader fileReader = File.OpenText(PathToFile))
{
var csv = new CsvReader(fileReader, CultureInfo.InvariantCulture);
csv.Read();
csv.ReadHeader();
string[] header = csv.Context.HeaderRecord;
int extractedIndex = Array.IndexOf(header, columnExtracted);
while (csv.Read())
{
string[] row = csv.Context.Record;
string column = row[extractedIndex];
result.Add(column);
}
}
return result;
This should work if you want each row as a string array.
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
using (CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
writer.WriteLine("Id,Name,Column3,Column4,Column5");
writer.WriteLine("1,One,Item1,Item2,Item3");
writer.WriteLine("2,Two,Item4,Item5,Item6");
writer.Flush();
stream.Position = 0;
reader.BaseStream.Position = 0;
csv.Read();
csv.ReadHeader();
string[] header = csv.Context.HeaderRecord;
var columnExtracted = "Column3";
int extractedIndex = Array.IndexOf(header, columnExtracted);
while (csv.Read())
{
string[] row = csv.Context.Record;
var column = row[extractedIndex];
Console.WriteLine(column);
}
}
Console.ReadKey();
I'm using NPOI to export data into excel.
So I created a List that will pull data from my database.
Now My question is how can I read my list data and write the data on my excel Sheet.
The following is my part of my code:
IWorkbook workbook;
workbook = new NPOI.XSSF.UserModel.XSSFWorkbook();
ISheet excelSheet = workbook.CreateSheet("Candidates");
IRow row = excelSheet.CreateRow(0);
foreach (var data in ApplicationList)
{
}
workbook.Write(fs);
So basically I need help on foreach (var data in ApplicationList)
While writing data cells can be created and SetCellValue can help set the data.
Below I have tried to iterate over a single column and list of strings.
This works fine on my system.
IWorkbook workbook = new HSSFWorkbook();
ISheet excelSheet = workbook.CreateSheet("Candidates");
IRow row = excelSheet.CreateRow(0);
var applicantList = new List<string> { "David", "Paul" };
var excelColumns = new[] { "Name" };
IRow headerRow = excelSheet.CreateRow(0);
var headerColumn = 0;
excelColumns.ToList().ForEach(excelColumn =>
{
var cell = headerRow.CreateCell(headerColumn);
cell.SetCellValue(excelColumn);
headerColumn++;
});
var rowCount = 1;
applicantList.ForEach(applicant => {
var row = excelSheet.CreateRow(rowCount);
var cellCount = 0;
excelColumns.ToList().ForEach(column => {
var cell = row.CreateCell(cellCount);
cell.SetCellValue(applicant);
cellCount++;
});
rowCount++;
});
var stream = new MemoryStream();
workbook.Write(stream);
string FilePath = "/Users/hemkumar/hem.xls"; //path to download
FileStream file = new FileStream(FilePath, FileMode.CreateNew,
FileAccess.Write);
stream.WriteTo(file);
file.Close();
stream.Close();
I hope it helps.
I know I am a little late here but I think it may help others
I have developed an excel utility with the use of the NPOI package, which can
Simply takes your data table or the collection
And Returns you excel while maintaining all the data table/list data type intact in the excel.
Github Code repo.: https://github.com/ansaridawood/.NET-Generic-Excel-Export-Sample/tree/master/GenericExcelExport/ExcelExport
Looking for a code explanation, you can find it here:
https://www.codeproject.com/Articles/1241654/Export-to-Excel-using-NPOI-Csharp-and-WEB-API
It uses NPOI DLL and it has 2 cs files to include and then you are good to go
Below is the first file for reference AbstractDataExport.cs:
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
namespace GenericExcelExport.ExcelExport
{
public interface IAbstractDataExport
{
HttpResponseMessage Export(List exportData, string fileName, string sheetName);
}
public abstract class AbstractDataExport : IAbstractDataExport
{
protected string _sheetName;
protected string _fileName;
protected List _headers;
protected List _type;
protected IWorkbook _workbook;
protected ISheet _sheet;
private const string DefaultSheetName = "Sheet1";
public HttpResponseMessage Export
(List exportData, string fileName, string sheetName = DefaultSheetName)
{
_fileName = fileName;
_sheetName = sheetName;
_workbook = new XSSFWorkbook(); //Creating New Excel object
_sheet = _workbook.CreateSheet(_sheetName); //Creating New Excel Sheet object
var headerStyle = _workbook.CreateCellStyle(); //Formatting
var headerFont = _workbook.CreateFont();
headerFont.IsBold = true;
headerStyle.SetFont(headerFont);
WriteData(exportData); //your list object to NPOI excel conversion happens here
//Header
var header = _sheet.CreateRow(0);
for (var i = 0; i < _headers.Count; i++)
{
var cell = header.CreateCell(i);
cell.SetCellValue(_headers[i]);
cell.CellStyle = headerStyle;
}
for (var i = 0; i < _headers.Count; i++)
{
_sheet.AutoSizeColumn(i);
}
using (var memoryStream = new MemoryStream()) //creating memoryStream
{
_workbook.Write(memoryStream);
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(memoryStream.ToArray())
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue
("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = $"{_fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
};
return response;
}
}
//Generic Definition to handle all types of List
public abstract void WriteData(List exportData);
}
}
and this the second and final file AbstractDataExportBridge.cs:
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text.RegularExpressions;
namespace GenericExcelExport.ExcelExport
{
public class AbstractDataExportBridge : AbstractDataExport
{
public AbstractDataExportBridge()
{
_headers = new List<string>();
_type = new List<string>();
}
public override void WriteData<T>(List<T> exportData)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
{
var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
_type.Add(type.Name);
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ??
prop.PropertyType);
string name = Regex.Replace(prop.Name, "([A-Z])", " $1").Trim(); //space separated
//name by caps for header
_headers.Add(name);
}
foreach (T item in exportData)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
IRow sheetRow = null;
for (int i = 0; i < table.Rows.Count; i++)
{
sheetRow = _sheet.CreateRow(i + 1);
for (int j = 0; j < table.Columns.Count; j++)
{
ICell Row1 = sheetRow.CreateCell(j);
string type = _type[j].ToLower();
var currentCellValue = table.Rows[i][j];
if (currentCellValue != null &&
!string.IsNullOrEmpty(Convert.ToString(currentCellValue)))
{
if (type == "string")
{
Row1.SetCellValue(Convert.ToString(currentCellValue));
}
else if (type == "int32")
{
Row1.SetCellValue(Convert.ToInt32(currentCellValue));
}
else if (type == "double")
{
Row1.SetCellValue(Convert.ToDouble(currentCellValue));
}
}
else
{
Row1.SetCellValue(string.Empty);
}
}
}
}
}
}
For a detailed explanation, refer link provided in the beginning.
I'm using NPOI to export data into excel too.
But I have a list that will pull data from another excel file that created by NPOI.
Anyway, I think my solution to solve this problem, which is not much different from yours, can be effective.
After you see the code sample below, read the description.
await using var stream = new FileStream(#"C:\Users\Sina\Desktop\TestExcel.xlsx", FileMode.OpenOrCreate, FileAccess.Write);
IWorkbook workbook = new XSSFWorkbook();
var excelSheet = workbook.CreateSheet("TestSheet");
for (var i = 0; i < MyDataList.Count(); i++)
{
var row = excelSheet.CreateRow(i);
for (var j = 0; j < MyDataList[i].Cells.Count(); j++)
{
var cell = row.CreateCell(j);
cell.SetCellValue(MyDataList[i].Cells[j].ToString());
}
}
workbook.Write(stream);
As I said, instead of the list you got the data from your database, I've used a list that has data from another excel file that I pulled through NPOI.
You can see it in the code snippet above (MyDataList).
It is of type (List<IRow>).
You have to create as many rows as there are data in your list, so create it in a loop each time. var row = excelSheet.CreateRow(i)
Now notice that each row has several cells and I fill the cells with another loop and you need to create any number of cells in your row, so create it in this loop each time. var cell = row.CreateCell(j)
You can now use cell.SetCellValue() to set each cell data then use the data in your list instead of MyDataList[i].Cells[j] in that.
Note that the input type of the SetCellValue() method must be a string.
Now I want to add that I also used the AddRange() method instead of the second loop (like this - row.Cells.AddRange(FailedRowList[i].Cells)) but it didn't work, so if you can use that I would appreciate if you say it and let me know more. I hope my answer was helpful.
Thanks
I have a pdf with buttons that take you out to web links. I used iTextSharp to split these into separate PDFs (1 per page) per outside requirements. ISSUE: Any button that has multiple positions, lost the actions.
QUESTION: Does anyone know how to update these actions? I can open the new file, but I'm not sure how to go about using the PdfStamper to add an AA to this Annotation
So when opening the original file, you could get to the Additional Action by doing this:
var r = new PdfReader(f.FullName);
var positionsOfThisButton = r.AcroFields.GetFieldPositions("14");
var field = r.AcroForm.GetField("14")
var targetObject = PdfReader.GetPdfObject(field.Ref);
var kids = targetObject.GetAsArray(PdfName.KIDS);
foreach (var k in kids){
var ko = (PdfDictionary)(k.IsIndirect() ? PdfReader.GetPdfObject(k) : k);
var aaObj = ko.Get(PdfName.AA);
//(aaObj is NULL in the new file)
var aa = (PdfDictionary)(aaObj.IsIndirect() ? PdfReader.GetPdfObject(aaObj) : aaObj);
var dObj = aa.Get(PdfName.D);
var d = (PdfDictionary)(dObj.IsIndirect() ? PdfReader.GetPdfObject(dObj) : dObj);
Debug.WriteLine("S:" + d.GetAsName(PdfName.S).ToString() );
//returns S:/Uri
Debug.WriteLine("URI:" + d.GetAsString(PdfName.URI).ToString() );
//returns URI:http://www.somesite.com/etc
}
Thanks for any help.
FYI ONLY - The following is how I split the files:
List<byte[]> Get(FileInfo f) {
List<byte[]> outputFiles = new List<byte[]>();
var reader = new PdfReader(f.FullName);
int n = reader.NumberOfPages;
reader.Close();
for (int i = n; i > 0; i--) {
reader = new PdfReader(f.FullName);
using (var document = new Document(reader.GetPageSizeWithRotation(1))) {
using (var outputStream = new MemoryStream()) {
using (var writer = new PdfCopy(document, outputStream)) {
writer.SetMergeFields();
writer.PdfVersion = '6';
document.Open();
writer.AddDocument(reader, new List<int> { i });
document.Close();
writer.Close();
}
outputFiles.Insert(0, outputStream.ToArray());
}
}
reader.Close();
}
return outputFiles;
}