Best and easiest way to export all the data from a datatable to an excel to get it downloaded using C#? - datatable

Using C#, which is the best and easiest way to export all the data from a datatable to an excel to get it downloaded?

I use Microsoft Interop.
Here is some sample code to get you started.
There are probably hundreds of tutorials which are better than the below. I have removed much of the code I use so I doubt the following will compile, but with careful reading, and some investigation into tutorials, you should be able to accomplish what you need.
public static void ExportToExcel(DataSet dsTodo, string strPathToSaveFile)
{
try
{
int numSteps = (dsTodo != null ? dsTodo.Tables.Count * 2 : 1);
Microsoft.Office.Interop.Excel.ApplicationClass ExcelApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
Workbook xlWorkbook = ExcelApp.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
if (dsTodo.Tables.Count > 0)
{
for (int i = dsTodo.Tables.Count; i > 0; i--)
{
Sheets xlSheets = null;
Worksheet xlWorksheet = null;
//Create Excel Sheets
xlSheets = ExcelApp.Sheets;
xlWorksheet = (Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);
System.Data.DataTable table = dsTodo.Tables[i - 1];
xlWorksheet.Name = table.TableName;
for (int j = 1; j < table.Columns.Count + 1; j++)
{
ExcelApp.Cells[1, j] = table.Columns[j - 1].ColumnName;
}
var excelData = new object[table.Rows.Count, table.Columns.Count];
for (int rowJ = 0; rowJ < table.Rows.Count; rowJ++)
{
for (int colI = 0; colI < table.Columns.Count; colI++)
{
excelData[rowJ, colI] = table.Rows[rowJ][colI];
}
}
int startCol = 1;
int endCol = startCol + table.Columns.Count - 1;
int startRow = 2;
int endRow = startRow + table.Rows.Count - 1;
string startLoc = GetCellFromCoords(startCol, startRow);
string endLoc = GetCellFromCoords(endCol, endRow);
//ExcelApp.get_Range(startLoc, endLoc).Value2 = excelData;
try
{
Range valRange = ExcelApp.get_Range(startLoc, endLoc);
valRange.Value2 = excelData;
}

Related

Is it possible to convert an AutoCAD solid3d entity to an Eyeshot brep entity and add it to the Eyeshot model viewport?

I am drawing a Cad Solid3d Entity by changing it to Brep and approaching the face,
but the shape is different. what's wrong
Or is there a way to directly import Autocad solid3d entity into the Eyeshot Model Viewport without redrawing with geometry information?
Below is my code
public void Main()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
CivilDocument cdoc = CivilApplication.ActiveDocument;
using (doc.LockDocument())
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
List<GBrep.Face> gFaces = new List<GBrep.Face>();
ObjectId solid3dId = EditorInputUtil.GetEntityId(ed, typeof(Solid3d));
GBRepView gBRepView = new GBRepView();
using (Solid3d solid = tr.GetObject(solid3dId, OpenMode.ForWrite) as Solid3d)
using (Brep brep = new Brep(solid))
{
foreach (Face face in brep.Faces)
{
Autodesk.AutoCAD.Geometry.NurbSurface nurbSurface = face.GetSurfaceAsNurb();
int uDegree = nurbSurface.DegreeInU;
int vDegree = nurbSurface.DegreeInV;
KnotCollection uKnotVector = nurbSurface.UKnots;
KnotCollection vKnotVector = nurbSurface.VKnots;
double[] uKnots = ConvertKnotVector(uKnotVector);
double[] vKnots = ConvertKnotVector(vKnotVector);
Point3dCollection p3ts = nurbSurface.ControlPoints;
Point4D[,] controlPoints = ConvertControlPoints(p3ts, nurbSurface.NumControlPointsInU, nurbSurface.NumControlPointsInV);
GSurface gSurface = new GSurface(uDegree, uKnots, vDegree, vKnots, controlPoints);
gBRepView.GetModel.Entities.Add(new devDept.Eyeshot.Entities.Surface(gSurface));
}
}
gBRepView.ShowDialog();
}
}
}
private Point4D[,] ConvertControlPoints(Point3dCollection point3ds, int uNums, int vNums)
{
Point4D[,] controlPoints = new Point4D[uNums, vNums];
int count = 0;
for (int i = 0; i < uNums; i++)
{
for (int j = 0; j < vNums; j++)
{
Point3d cadPoint = point3ds[count];
controlPoints[i, j] = new Point4D(cadPoint.X, cadPoint.Y, cadPoint.Z);
count++;
}
}
return controlPoints;
}

How do I convert a Word Table into an embedded Excel Worksheet?

I have a document that has multiple Word Tables. I need to convert them into embedded Excel Worksheets (or COM Objects). I've been able to "import" the Word Tables into Excel using the following:
Excel.Application xlApp = new Excel.Application();
// Call the conversion tool
for (int i = 1; i <= curDoc.Tables.Count; i++ )
{
Word.Table tbl = curDoc.Tables[i];
Word.Range tblLoc = tbl.Range;
// Used for debugging.
xlApp.Visible = true;
if (xlApp == null)
{
messageAlert = "Excel could not be started. Check that your office installation and project references are correct.";
break;
}
Excel.Workbook wb = xlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];
if (ws == null)
{
messageAlert = "Worksheet could not be created. Check that your office installation and project reference are correct.";
break;
}
Word.Range rng = tbl.ConvertToText(Separator: ";", NestedTables: false);
string sData = rng.Text;
string[] rows = sData.Split('\r');
int r = 1, c = 1;
int numRows = rows.Count();
int numCols = rows[0].Split(';').Count();
foreach (string row in rows)
{
string[] cells = row.Split(';');
foreach (string cell in cells)
{
ws.Cells[r, c].Value = cell;
c += 1;
}
r += 1;
c = 1;
}
Problem is whenever I copy the contents back into the document, a new Word Table is created instead of an Excel Worksheet. How do I either import an Excel Worksheet into Word, or directly convert the tables into Excel Worksheets?
In order to do this, you'll have to first save the excel worksheet and then import it as an OLEObject. Here's an example:
public void ConvertTables()
{
string messageAlert = "";
Word.Application curApp = Globals.ThisAddIn.Application;
Word.Document curDoc = curApp.ActiveDocument;
if (curDoc.Tables.Count > 0)
{
Excel.Application xlApp = new Excel.Application();
//Used for debugging.
//xlApp.Visible = true;
//Call the conversion tool
for (int i = 1; i <= curDoc.Tables.Count; i++ )
{
Word.Table tbl = curDoc.Tables[i];
Word.Range tblLoc = tbl.Range;
if (xlApp == null)
{
messageAlert = "Excel could not be started. Check that your office installation and project references are correct.";
break;
}
Excel.Workbook wb = xlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];
if (ws == null)
{
messageAlert = "Worksheet could not be created. Check that your office installation and project reference are correct.";
break;
}
Word.Range rng = tbl.ConvertToText(Separator: ";", NestedTables: false);
string sData = rng.Text;
string[] rows = sData.Split('\r');
int r = 1, c = 1;
int numRows = rows.Count();
int numCols = rows[0].Split(';').Count();
foreach (string row in rows)
{
string[] cells = row.Split(';');
foreach (string cell in cells)
{
ws.Cells[r, c].Value = cell;
c += 1;
}
r += 1;
c = 1;
}
ws.SaveAs("C:\\temp\\test.xlsx");
rng.Text = "";
rng.InlineShapes.AddOLEObject(ClassType: "Excel.Sheet.12", FileName: "C:\\temp\\test.xlsx");
ws.Range["A1", ws.Cells[numRows, numCols]].Value = "";
ws.SaveAs("C:\\Temp\\test.xlsx");
}
xlApp.Quit();
messageAlert = "Tables converted";
}
else
{
// No tables found
messageAlert = "No tables found within the document";
}
MessageBox.Show(messageAlert);
}

Count number of emails in outlook folder

I want to count the number of mails i received which has word say 'xyz' in subject line.But I do not want it to count duplicates, I mean if I get a mail with subject 'xyz' and I reply to it including myself I want that to be counted as 1 not 2. Is it possible in outlook?
Yeah that's possible definetly, you did not specify the techno you would use but a sample code using interop could be:
var outlookApp = new Outlook.Application();
var mapi = outlookApp.GetNamespace("MAPI")
var root = mapi.GetDefaultFolder(OlDefaultfolders.olFolderInbox)
var folders = root.Folders;
int count = 0;
for(int i = folders.Count; i >= 1; i--)
{
var folder = folders[i];
count += GetCount(folder, 0);
Marshal.ReleaseComObject(folder);
}
Marshal.ReleaseComObject(folders);
//... function
private int GetCount(MAPIFolder folder, int count)
{
var folderItems = folder.Items;
if(folderItems != null && folderItems.Count >= 1)
{
for(int i = folderItems.Count; i >= 1; i--)
{
//Check item.Subject for string logic
count++;
//Add item in collection variable to check duplicates,
//generate an id with subject + creationtime for tracking?
}
}
if(folder.Folders != null && folder.Folders >= 1)
{
var subFolders = folder.Folders;
for(int i = subfolders.Count; i >= 1; i--)
{
var subFolder = subFolders[i]
count += GetCount(subFolder, count);
Marshal.ReleaseComObject(subfolder);
}
}
Marshal.ReleaseComObject(folderItems);
return count;
}
Hope it helps someone,

Abcpdf copyable/selectable text

i'm using websupergoos abcpdf to convert html pages to pdf via addimageurl.
Works great, but the resulting pdf does not allow the user to select text and copy. All is one 'image'.
Is it possible to do this? Which are the settings to use?
This is my current code. The commented "flatten" does not seem to do anything relevant. The HttpStream simply forewards the pdf to users as a doc.
var doc = new Doc();
doc.HtmlOptions.UseScript = true;
doc.Units = "mm";
doc.MediaBox.String = "0 0 210 297";
doc.Rect.String = doc.MediaBox.String;
doc.Rect.Inset(10.0, 10.0);
doc.SetInfo(0, "License", abcpdfkey);
doc.HtmlOptions.UseScript = true;
doc.HtmlOptions.AddMovies = true;
doc.HtmlOptions.RetryCount = 0;
doc.HtmlOptions.ContentCount = 1;
doc.Page = doc.AddPage();
for (int i = doc.AddImageUrl(url); doc.Chainable(i); i = doc.AddImageToChain(i))
{
doc.Page = doc.AddPage();
}
int pageCount = doc.PageCount;
for (int j = 1; j <= pageCount; j++)
{
doc.PageNumber = j;
// doc.Flatten();
}
this.HttpStream(doc.GetData(), filename);
Before sending the PDF to the HTTP stream, you can set the encryption properties
The CanCopy Property sets if the user can copy text from the PDF
To set it add the following code:
doc.Encryption.CanCopy = true;
You may need to set doc.Encryption.CanExtract as well

split one big datatable to two separated datatables

I´m exporting datatables to Excel workbook. Problem is that the datatable holds 90000 rows and excel can only hold 67000 rows in every sheet.
So..
How can i divide one big datatable to two datatables, maybe with Linq ?
Then i can have datatable1 in sheet1 and datatable2 in sheet2
Sincerly
agh
Assuming that you're getting the 90,000 rows for this DataTable from a database somewhere, the most efficient approach would be to modify your SELECT statement into two new SELECT statements, each of which returns < 67,000 rows, and then do everything else the same.
Split your recordset. Perform one SELECT that extracts all 90,000 rows, and split it on Excel import step.
private List<DataTable> CloneTable(DataTable tableToClone, int countLimit)//Split function
{
List<DataTable> tables = new List<DataTable>();
int count = 0;
DataTable copyTable = null;
foreach (DataRow dr in tableToClone.Rows)
{
if ((count++ % countLimit) == 0)
{
copyTable = new DataTable();
copyTable = tableToClone.Clone();
copyTable.TableName = "Sample" + count;
tables.Add(copyTable);
}
copyTable.ImportRow(dr);
}
return tables;
}
protected void LinkReport_Click(object sender, EventArgs e)
{
DataTable dt2 = (DataTable)ViewState["dtab"];
List<DataTable> dt1 = CloneTable(dt2, 5);
DataSet ds = new DataSet("dst");
for (int i = 0; i < dt1.Count; i++)
{
ds.Tables.Add(dt1[i]);
}
string filePath = Server.MapPath("Reports/").ToString() + "master.xls";
FileInfo file = new FileInfo(filePath);
if (file.Exists)
{
file.Delete();
}
Export(ds, filePath);// Export into Excel
}
Clone - The fastest method to create tables with original columns structure is Clone method.
Export into Excel
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
}
finally
{
GC.Collect();
}
}
public void Export(DataSet ds, string filePath)
{
string data = null;
string columnName = null;
int i = 0;
int j = 0;
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
//Excel.Worksheet xlWorkSheet;
Excel.Worksheet xlWorkSheet = null;
object misValue = System.Reflection.Missing.Value;
Excel.Range range;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Add(misValue);
//xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
for (int l = 0; l < ds.Tables.Count; l++)
{
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(l + 1);
xlWorkSheet.Cells[1, 1] = "Report";
xlWorkSheet.get_Range("A1:D1", Type.Missing).Merge(Type.Missing);
xlWorkSheet.get_Range("A1", "D1").Font.Bold = true;
xlWorkSheet.Cells.Font.Name = "Courier New";
if (l == 0)
{
xlWorkSheet.Name = "Sheet1";
}
else if (l == 1)
{
xlWorkSheet.Name = "Sheet2";
}
else if (l == 2)
{
xlWorkSheet.Name = "Sheet3";
}
else if (l == 3)
{
xlWorkSheet.Name = "Sheet4";
}
else if (l == 4)
{
xlWorkSheet.Name = "Sheet5";
}
for (i = 0; i <= ds.Tables[l].Rows.Count - 1; i++)
{
for (j = 0; j <= ds.Tables[l].Columns.Count - 1; j++)
{
columnName = ds.Tables[l].Columns[j].ColumnName.ToString();
xlWorkSheet.Cells[3, j + 1] = columnName;
data = ds.Tables[l].Rows[i].ItemArray[j].ToString();
xlWorkSheet.Cells[i + 5, j + 1] = data;
}
}
}
//for (i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
//{
// for (j = 0; j <= ds.Tables[0].Columns.Count - 1; j++)
// {
// data = ds.Tables[0].Rows[i].ItemArray[j].ToString();
// xlWorkSheet1.Cells[i + 1, j + 1] = data;
// }
//}
xlWorkBook.SaveAs(filePath, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
// kill all excel processes
Process[] pros = Process.GetProcesses();
for (int p = 0; p < pros.Length; p++)
{
if (pros[p].ProcessName.ToLower().Contains("excel"))
{
pros[p].Kill();
break;
}
}
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
Try this One.. I have Worked out in Visual Studio 2005
DataTable[] splittedtables = dt.AsEnumerable()
.Select((row, index) => new { row, index })
.GroupBy(x => x.index / Input From User) // integer division, the fractional part is truncated
.Select(g => g.Select(x => x.row).CopyToDataTable())
.ToArray();
This should work.

Resources