Convert CSV to Excel Windows Phone 8 - excel

with windows phone 8 I need to be able to open a CSV file in Excel using C#. Their is an app on the market now called Excel Extensions that converts the csv file locally.
I have tired converting the CSV file using open office XML but that didn't work. and I want to do it locally so no web services.
Anyone know how I can convert the CSV file to Excel on the Windows Phone 8 platform?

THEORY
You have a two distinct options: (1) doing most of the work on the WP8 client (2) or doing most of the work on a remote server.
For option #2 of using a remote server: Expose a WCF service that takes in the CSV file, parses the CSV to find its logical 2D table structure, use ClosedXML to save a new XLSX file and return that to the client. This option is the most straightforward but also requires network connectivity and a hosted server.
For option #1 of not using a remote server: read the CSV file, copy the CSV data into to an XLSX file, save the XLSX into IsoStore and launch excel with that file. I've written about this topic in the past # How can we create, write and read an excel file for Windows Phone 8
One thing you'll have to do quite a lot of work is writing a XLSX file in pure WP7 C#. You'll either have to convert 3rd party libraries that write XLSX to support WP7/WP8, or convert simple end-to-end C# code samples to WP7/WP8. Both aren't simple. Converting ClosedXML is possible but DocumentFormat.OpenXml's dependency on WPF's WindowsCore is a problem. Another option is to write your own OpenXML C# implementation like Chris Klug did here for Word OpenXML on Silverlight and was ported to WP7 later on. The key is using OpenXML specification for your advantage.
LIVE CODE SAMPLE
For example, looking at Chris Klug's Silverlight Excel OpenXML article it's possible to take his code for Ag.OpenXML and OpenXML.Silverlight.Spreadsheet port those to WP8 and then simply invoke them. I did just that. Here's how to get that experimental source code and get started:
1) Download and unzip # http://JustinAngel.net/Storage/OpenXML.Silverlight.Spreadsheet.WP8.zip
2) Add a reference to the csproj, or to the DLLs OpenXML.Silverlight.Spreadsheet.WP8.dll & SharpZipLib.dll from "OpenXML.Silverlight.Spreadsheet.WP8\Bin\Debug".
3) Add the following code snippet that saves a SpreedsheetDocument file into your app's WP8 IsoStore and then launches it in Word using WP8 app2app file associations.
private async void SaveXlsxToIsoStoreAndLaunchInExcel(SpreadsheetDocument doc)
{
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isoStore.FileExists("myFile.xlsx"))
isoStore.DeleteFile("myFile.xlsx");
using (var s = isoStore.CreateFile("myFile.xlsx"))
using (IStreamProvider storage = new ZipStreamProvider(s))
{
doc.Save(storage);
}
Launcher.LaunchFileAsync(
await ApplicationData.Current.LocalFolder.GetFileAsync("myFile.xlsx"));
}
}
4) Invoke the above code snippet with Chris's sample document:
private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
SpreadsheetDocument doc = new SpreadsheetDocument();
doc.ApplicationName = "SilverSpreadsheet";
doc.Creator = "Chris Klug";
doc.Company = "Intergen";
SharedStringDefinition str1 = doc.Workbook.SharedStrings.AddString("Column 1");
SharedStringDefinition str2 = doc.Workbook.SharedStrings.AddString("Column 2");
SharedStringDefinition str3 = doc.Workbook.SharedStrings.AddString("Column 3");
doc.Workbook.Sheets[0].Sheet.Rows[0].Cells[0].SetValue(str1);
doc.Workbook.Sheets[0].Sheet.Rows[0].Cells[1].SetValue(str2);
doc.Workbook.Sheets[0].Sheet.Rows[0].Cells[2].SetValue(str3);
doc.Workbook.Sheets[0].Sheet.Rows[1].Cells[0].SetValue("Value 1");
doc.Workbook.Sheets[0].Sheet.Rows[1].Cells[1].SetValue(1);
doc.Workbook.Sheets[0].Sheet.Rows[1].Cells[2].SetValue(1001);
doc.Workbook.Sheets[0].Sheet.Rows[2].Cells[0].SetValue("Value 2");
doc.Workbook.Sheets[0].Sheet.Rows[2].Cells[1].SetValue(2);
doc.Workbook.Sheets[0].Sheet.Rows[2].Cells[2].SetValue(1002);
doc.Workbook.Sheets[0].Sheet.Rows[3].Cells[0].SetValue("Value 3");
doc.Workbook.Sheets[0].Sheet.Rows[3].Cells[1].SetValue(3);
doc.Workbook.Sheets[0].Sheet.Rows[3].Cells[2].SetValue(1003);
doc.Workbook.Sheets[0].Sheet.Rows[4].Cells[0].SetValue("Value 4");
doc.Workbook.Sheets[0].Sheet.Rows[4].Cells[1].SetValue(4);
doc.Workbook.Sheets[0].Sheet.Rows[4].Cells[2].SetValue(1004);
TablePart table = doc.Workbook.Sheets[0].Sheet.AddTable("My Table", "My Table", doc.Workbook.Sheets[0].Sheet.Rows[0].Cells[0], doc.Workbook.Sheets[0].Sheet.Rows[4].Cells[2]);
table.TableColumns[0].Name = str1.String;
table.TableColumns[1].Name = str2.String;
table.TableColumns[2].Name = str3.String;
doc.Workbook.Sheets[0].Sheet.AddColumnSizeDefinition(0, 2, 20);
doc.Workbook.Sheets[0].Sheet.Rows[5].Cells[1].SetValue("Sum:");
doc.Workbook.Sheets[0].Sheet.Rows[5].Cells[2].Formula = "SUM(" + doc.Workbook.Sheets[0].Sheet.Rows[1].Cells[2].CellName + ":" + doc.Workbook.Sheets[0].Sheet.Rows[4].Cells[2].CellName + ")";
SaveXlsxToIsoStoreAndLaunchInExcel(doc);
}
5) When running this code snippet we can see the following warning popup and then the excel spreadsheet. Feel free to improve upon my hasty Silverlight-->WP8 port and remove that warning.

Related

Excel and Libre Office conflict over Open XML output

Open XML is generating .xlsx files that can be read by Open Office, but not by Excel itself.
With this as my starting point( Export DataTable to Excel with Open Xml SDK in c#) I have added code to create a .xlsx file. Attempting to open with Excel, I'm asked if I want to repair the file. Saying yes gets "The workbook cannot be opened or repaired by Microsoft Excel because it's corrupt." After many hours of trying to jiggle the data from my table to make this work, I finally threw up my hands in despair and made a spreadsheet with a single number in the first cell.
Still corrupt.
Renaming it to .zip and exploring shows intact .xml files. On a whim, I took a legit .xlsx file created by Excel, unzipped it, rezipped without changing contents and renamed back to .xlsx. Excel declared it corrupt. So this is clearly not a content issue, but file a format issue. Giving up on Friday, I sent some of the sample files home and opened them there with Libre Office. There were no issues at all. File content was correct and Calc had no problem. I'm using Excel for Office 365, 32 bit.
// ignore the bits (var list) that get data from the database. I've reduced this to just the output of a single header line
List< ReportFilingHistoryModel> list = DB.Reports.Report.GetReportClientsFullHistoryFiltered<ReportFilingHistoryModel>(search, client, report, signature);
MemoryStream memStream = new MemoryStream();
using (SpreadsheetDocument workbook = SpreadsheetDocument.Create(memStream, SpreadsheetDocumentType.Workbook))
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new Workbook();
workbook.WorkbookPart.Workbook.Sheets = new Sheets();
var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
var sheetData = new SheetData();
sheetPart.Worksheet = new Worksheet(sheetData);
Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<Sheet>().Count() > 0)
{
sheetId = sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = "History" };
sheets.Append(sheet);
Row headerRow = new Row();
foreach( var s in "Foo|Bar".Split('|'))
{
var cell = new Cell();
cell.DataType = CellValues.Number;
cell.CellValue = new CellValue("5");
headerRow.AppendChild(cell);
}
sheetData.AppendChild(headerRow);
}
memStream.Seek(0, SeekOrigin.Begin);
Guid result = DB.Reports.Report.AddClientHistoryList( "test.xlsx", memStream.GetBuffer(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
return Ok(result);
This should just work. I've noticed other stack overflow discussions that direct back to the first link I mentioned above. I seem to be doing it right (and Calc concurs). There have been discussions of shared strings and whatnot, but by using plain numbers I shouldn't be having issues. What am I missing here?
In working on this, I went with the notion that some extraneous junk on the end of a .zip file is harmless. 7-Zip, Windows Explorer and Libre Office all seem to agree (as does some other zip program I used at home whose name escapes me). Excel, however, does not. Using the pointer at memStream.GetBuffer() was fine, but using its length was not. (The preceding Seek() was unnecessary.) Limiting the write of the data to a length equal to the current output position keeps Excel from going off the rails.

QT Excel - Open to Read/Write

I'd like to know what's the best way to open excel file (.xlsx) (Need to write and read or eventually only read)
I've already tried this (it's only test):
void MainWindow::openExcel()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC", "xls_connection");
db.setDatabaseName("DRIVER={Microsoft Excel Driver (*.xls,*.xlsx,*.xlsm,*.xlsb)};DBQ=" + QString ("C:\\Users\\User\\Desktop\\file.xlsx") );
if(db.open())
{
QSqlQuery query("select * from [" + QString("Sheet1") + "$A1:B5]");
while (query.next())
{
//reading columns
QString column1= query.value(0).toString();
qDebug()<<column1;
}
db.close();
QSqlDatabase::removeDatabase("xls_connection");
}
else
{
qDebug()<<"Failed";
}
}
but it couldn't open such file ("Failed"). I would be glad if anyone could say where's a problem
//Maybe also recommend any good books or tutorials for QT?
To use ODBC for Excel on Windows, the MS Access Database Engine must be downloaded as mentioned in the wiki Note from which this sample code was tested (Win7/ qt4.9 , Win10/ qt 5.7) , then the connection can work. alternatively in the same Qt wiki Content, you can find different ways of opening MS Excel with Qt.
You can use ActivX object to work with excel file -
ActiveX Excel example
Other option to read-write into excel file format (.xlsx) -
QtXlsxWriter

Testing excel with Winappdriver

Where can i find a good example of testing an excel addin project with custom ribbon elements, using winappdriver.
What i have so far throws an exception:
System.InvalidOperationException
An element could not be located on the page using the given search parameters.
I am using latest winappdriver
Code:
private const string ExcelAppId = #"C:\Program Files (x86)\Microsoft Office\root\Office16\EXCEL.EXE";
private const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
DesiredCapabilities appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", ExcelAppId);
appCapabilities.SetCapability("deviceName", "WindowsPC");
appCapabilities.SetCapability("platformName", "Windows");
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
session.FindElementByName("Blank workbook").Click();
I'm working on automated testing of an Excel add-in with WinAppDriver.
In my case I started Excel without the splash screen. Supply /e as app parameter to achieve it.
session.SetCapability("appArguments", "/e");
From this point onward, you'll be able to find the "File" menu and "New" menu by name and click them.
Add a few seconds of explicit wait and proceed to finding "Blank Workbook" WindowsElement the same way.
I hope this answers your question, post here if more help is needed.
I've been experimenting with WinAppDriver for a few months now, also preparing a Udemy course on the subject which is almost ready to publish. It's an interesting toolkit.
You need to install Appium.WebDriver, Selenium.support, Selenium.webDriver from "Manage Nuget packages"
you can use appium code like:
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Windows;
class Excel
{
public void ExcelCase() {
WindowsDriver<WindowsElement> driver;
AppiumOptions desiredcap = new AppiumOptions();
desiredcap.AddAdditionalCapability("app", #"C:\Program Files\Microsoft Office\Office16\EXCEL.EXE");
driver = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), desiredcap);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
if (driver == null)
{
Console.WriteLine("App not running");
return;
}
}}
Try this code and comment if you face any issue.
I prefer to use: session.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5); instead of Thread.sleep(5).
Does it even open the excel when you start the test?
If by Name is not working, it doens't work to me sometimes either, you can use the accessibilityId
session.FindElementByAccessibilityId("AIOStartDocument").Click();
or use the keyboard shorcut to open the blank workbook, like this:
session.Keyboard.SendKeys(Keys.Alt + "f" + "l" + Keys.Alt);

I want to add new sheet to an existing csv file, but I dont know how to go about it

I want to add new sheet to an existing csv file, but I dont know how to go about it. I already opened the .csv file and i can access each element. so i want to create a new sheet on the existing .csv file and populate the cells with the data from the previous sheet.
class Program
{
static void Main(string[] args)
{
var reader = new StreamReader(File.OpenRead(#"C:\Users\Desktop\test.csv"));
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
//line = line.Skip(1);
var values = line.Split(',');
listA.Add(values[0]);
listB.Add(values[1]);
listA.ForEach(Console.WriteLine);
listB.ForEach(Console.WriteLine);
Console.ReadLine();
}
}
}
I'm going to post this as an answer, even though it's kind of a non-answer. CSV files are simple flat-text files that are comma delimited. There are no higher-level concepts to this file type such as sheets, or cells, workbooks, or formulas.
Since they are just simple text files that are specially formatted, there is no concept of sheets. Instead you can maybe create additional CSV files and name the files accordingly.
If you want to create Excel files, and have individual sheets you can use various libraries or the COM Interops to do this.
COM Interops are for direct connections to Excel natively. Here's a MSDN How-To for Excel. This allows you to create a special object that will allow you to use Excel's API even though it's not a managed API through the .NET Framework.
Here's an example on how to add a sheet in that situation:
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
Console.WriteLine("EXCEL could not be started. Check that your office installation and project references are correct.");
return;
}
xlApp.Visible = true;
Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet); //adds worksheet to our workbook
Worksheet ws = (Worksheet)wb.Worksheets[1]; //access that worksheet linked into the workbook
if (ws == null)
{
Console.WriteLine("Worksheet could not be created. Check that your office installation and project references are correct.");
}
Another option is to use the Open XML SDK for Office, which can be used for the new Office formats (.xlsx for example). Personally, I've never used this library, but it's similar to Apache POI for the .NET Framework.

How can I programatically convert .xls and .csv files to .xlsx?

Is there a programmatic solution to this that does not involve having Office on the server?
Update:
This solution will be deployed in a .Net shop, so for now PHP and Java approaches aren't on the table (though I was impressed with the libraries themselves).
We will be receiving documents in csv, .xls, and .xlsx formats that need to be parsed and their data shoved into a DB. We're planning on using the OpenXML SDK for all of the parsing goodness and want to operate over only one file type.
You can achieve this using the Apache POI library for Java.
HSSF is the POI Project's pure Java implementation of the Excel '97(-2007) file format.
XSSF is the POI Project's pure Java implementation of the Excel 2007 OOXML (.xlsx) file format.
I've used it to read in a complete mix of .xls and .xlsx files, and I always output .xlsx.
For .csv files, import using the Super CSV library and export using the Apache POI library above.
The main motivation for Super Csv is to be the best, fastest and most programmer friendly free CSV package for Java.
Or use PHPExcel ( http://www.phpexcel.net ) if you want a PHP solution rather than java
For csv files i would recommend a combination of http://kbcsv.codeplex.com/ to read the csv file into a datatable and EPPPLUS to use its .FromDataTable Method to convert it to an xlsx file.
I works great for me and is very fast.
For reading xls files there is no free Implementation that I know of :(
and you can use for parse columns.
object columnValue = ws.Cells[i, ColIndex, i, ColIndex].Value; // get Specific cell.
you can use below method for .csv, xlsx, .txt files.
public yourReturnType compute()
{
#region .XLSX Section
if (FilePath.FullName.Contains(".xlsx") || FilePath.FullName.Contains(".xls"))
{
// Open and read the XlSX file.
using (var package = new ExcelPackage(FilePath))
{
ExcelWorkbook wb = package.Workbook; // Get the work book in the file
if (wb != null)
{
if (wb.Worksheets.Count > 0)
{
ExcelWorksheet ws = wb.Worksheets.First(); // Get the first worksheet
yourParseCode(ws);
}
} // if End.
} // using end.
}
#endregion
#region .CSV Section
if (FilePath.FullName.Contains(".csv") || FilePath.FullName.Contains(".txt"))
{
CSVParser c = new CSVParser(FilePath);
DataTable dt = c.ReadCSVFile();
using (ExcelPackage pck = new ExcelPackage())
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("temporary");
ws.Cells["A1"].LoadFromDataTable(dt, true);
yourParseCode (ws);
////pck.Save(); // no need to save this temporary sheet.
}
}
#endregion
return (yourReturnType );
}

Resources