|
Some resource from internet
| Posted at |
☆ |
|
Labels: C++
| Posted at |
☆ |
int main()
{
/* Student one;
strcpy(one.FullName, "Ernestine Waller");
strcpy(one.CompleteAddress, "824 Larson Drv, Silver Spring, MD 20910");
one.Gender = 'F';
one.Age = 16.50;
one.LivesInASingleParentHome = true;
ofstream ofs("fifthgrade.ros", ios::binary);
ofs.write((char *)&one, sizeof(one));
*/
Student two;
ifstream ifs("fifthgrade.ros", ios::binary);
ifs.read((char *)&two, sizeof(two));
cout << "Student Information\n";
cout << "Student Name: " << two.FullName << endl;
cout << "Address: " << two.CompleteAddress << endl;
if( two.Gender == 'f' || two.Gender == 'F' )
cout << "Gender: Female" << endl;
else if( two.Gender == 'm' || two.Gender == 'M' )
cout << "Gender: Male" << endl;
else
cout << "Gender: Unknown" << endl;
cout << "Age: " << two.Age << endl;
if( two.LivesInASingleParentHome == true )
cout << "Lives in a single parent home" << endl;
else
cout << "Doesn't live in a single parent home" << endl;
cout << "\n";
return 0;
}
Labels: Serialization
| Posted at |
☆ |
By Bipin Joshi May 14, 2001
Introduction
In simple words serialization is a process of storing the object instance to a disk file. Serialization stores state of the object i.e. member variable values to disk. Deserialization is reverse of serialization i.e. it's a process of reading objects from a file where they have been stored. In this code sample we will see how to serialize and deserialize objects using C#.
Following namespaces are involved in serialization process :
Example 1
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class SerialTest
{
public void SerializeNow()
{
ClassToSerialize c=new ClassToSerialize();
File f=new File("temp.dat");
Stream s=f.Open(FileMode.Create);
BinaryFormatter b=new BinaryFormatter();
b.Serialize(s,c);
s.Close();
}
public void DeSerializeNow()
{
ClassToSerialize c=new ClassToSerialize();
File f=new File("temp.dat");
Stream s=f.Open(FileMode.Open);
BinaryFormatter b=new BinaryFormatter();
c=(ClassToSerialize)b.Deserialize(s);
Console.WriteLine(c.name);
s.Close();
}
public static void Main(string[] s)
{
SerialTest st=new SerialTest();
st.SerializeNow();
st.DeSerializeNow();
}
}
public class ClassToSerialize
{
public int age=100;
public string name="bipin";
}
Explanation
Here we have our own class named ClassToSerialize. This class has two public valiables name and age with some default values. We will write this class to a disk file (temp.dat) using SerializeTest class.
SerializeTest class has two methods SerializeNow() and DeSerializeNow() which perform the task of serialization and deserialization respectively.
The general steps for serializing are :
The steps for de-serializing the object are similar. The only change is that you need to call deserialize method of BinaryFormatter object.
Now, let us see an example where we have used 'real' class with public and shared members and properties to encapsulate them. The class also uses another supporting class. This is just to make clear that if your class contains further classes, all the classes in the chain will be serialized.
Example 2
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class SerialTest
{
public void SerializeNow()
{
ClassToSerialize c=new ClassToSerialize();
c.Name="bipin";
c.Age=26;
ClassToSerialize.CompanyName="xyz";
File f=new File("temp.dat");
Stream s=f.Open(FileMode.Create);
BinaryFormatter b=new BinaryFormatter();
b.Serialize(s,c);
s.Close();
}
public void DeSerializeNow()
{
ClassToSerialize c=new ClassToSerialize();
File f=new File("temp.dat");
Stream s=f.Open(FileMode.Open);
BinaryFormatter b=new BinaryFormatter();
c=(ClassToSerialize)b.Deserialize(s);
Console.WriteLine("Name :" + c.Name);
Console.WriteLine("Age :" + c.Age);
Console.WriteLine("Company Name :" + ClassToSerialize.CompanyName);
Console.WriteLine("Company Name :" + c.GetSupportClassString());
s.Close();
}
public static void Main(string[] s)
{
SerialTest st=new SerialTest();
st.SerializeNow();
st.DeSerializeNow();
}
}
public class ClassToSerialize
{
private int age;
private string name;
static string companyname;
SupportClass supp=new SupportClass();
public ClassToSerialize()
{
supp.SupportClassString="In support class";
}
public int Age
{
get
{
return age;
}
set
{
age=value;
}
}
public string Name
{
get
{
return name;
}
set
{
name=value;
}
}
public static string CompanyName
{
get
{
return companyname;
}
set
{
companyname=value;
}
}
public string GetSupportClassString()
{
return supp.SupportClassString;
}
}
public class SupportClass
{
public string SupportClassString;
}
Example 3
The final example shows how to serialize array of objects.
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
public class SerialTest
{
public void SerializeNow()
{
ClassToSerialize[] c=new ClassToSerialize[3];
c[0]=new ClassToSerialize();
c[0].Name="bipin";
c[0].Age=26;
c[1]=new ClassToSerialize();
c[1].Name="abc";
c[1].Age=75;
c[2]=new ClassToSerialize();
c[2].Name="pqr";
c[2].Age=50;
ClassToSerialize.CompanyName="xyz";
File f=new File("temp.dat");
Stream s=f.Open(FileMode.Create);
BinaryFormatter b=new BinaryFormatter();
b.Serialize(s,c);
s.Close();
}
public void DeSerializeNow()
{
ClassToSerialize[] c;
File f=new File("temp.dat");
Stream s=f.Open(FileMode.Open);
BinaryFormatter b=new BinaryFormatter();
c=(ClassToSerialize[])b.Deserialize(s);
Console.WriteLine("Name :" + c[2].Name);
Console.WriteLine("Age :" + c[2].Age);
Console.WriteLine("Company Name :" + ClassToSerialize.CompanyName);
s.Close();
}
public static void Main(string[] s)
{
SerialTest st=new SerialTest();
st.SerializeNow();
st.DeSerializeNow();
}
}
public class ClassToSerialize
{
private int age;
private string name;
static string companyname;
public int Age
{
get
{
return age;
}
set
{
age=value;
}
}
public string Name
{
get
{
return name;
}
set
{
name=value;
}
}
public static string CompanyName
{
get
{
return companyname;
}
set
{
companyname=value;
}
}
}
Labels: Serialization
.period 句号
,comma 逗号
:colon 冒号
;semicolon 分号
!exclamation 惊叹号
?question mark 问号
 ̄hyphen 连字符
'apostrophe 省略号;所有格符号
dash 破折号
‘ ’single quotation marks 单引号
“ ”double quotation marks 双引号
( )parentheses 圆括号
[ ]square brackets 方括号
《 》French quotes 法文引号;书名号
...ellipsis 省略号
¨tandem colon 双点号
"ditto 同上
‖parallel 双线号
/virgule 斜线号
&ampersand = and
~swung dash 代字号
§section; division 分节号
→arrow 箭号;参见号
+plus 加号;正号
-minus 减号;负号
±plus or minus 正负号
×is multiplied by 乘号
÷is divided by 除号
=is equal to 等于号
≠is not equal to 不等于号
≡is equivalent to 恒等于号
≌is identical to 全等于号
≈is approximately equal to 约等于号
<is less than 小于号
>is more than 大于号
≮is not less than 不小于号
≯is not more than 不大于号
≤is less than or equal to 小于或等于号
≥is more than or equal to 大于或等于号
%per cent 百分之…
‰per mill 千分之…
∞infinity 无限大号
∝varies as 与…成比例
√(square) root 平方根
∵since; because 因为
∴hence 所以
∷equals, as (proportion) 等于,成比例
∠angle 角
⌒semicircle 半圆
⊙circle 圆
○circumference 圆周
πpi 圆周率
△triangle 三角形
⊥perpendicular to 垂直于
∪union of 并,合集
∩intersection of 交,通集
∫the integral of …的积分
∑(sigma) summation of 总和
°degree 度
′minute 分
″second 秒
#number …号
℃Celsius system 摄氏度
Labels: Others
| Posted at |
☆ |
Labels: Interoperability
| Posted at |
☆ |
By Majid Shahabfar
Introduction
The main goal of writing this article is to explain how we can mix the .NET library with the MFC library in very easy steps, gaining the benefits of .NET in unmanaged code such as MFC projects. So for this reason I’ve added ADO.NET in a MFC project to use the simple, type-safe and powerful functionalities of that library.
ADO.NET
In designing tools and technologies to meet the needs of today's developer, Microsoft recognized that an entirely new programming model for data access was needed, one that is built upon the .NET Framework. Building on the .NET Framework ensures that the data access technology would be uniform, components would share a common type system, design patterns and naming conventions. ADO.NET was designed to meet the needs of this new programming model: disconnected data architecture, tight integration with XML, common data representation with the ability to combine data from multiple and varied data sources, and optimized facilities for interacting with a database, all native to the .NET Framework.
Mixing Managed and Unmanaged code
To use managed code in a MFC projects we must change some MFC project settings and add some code to declare the .NET library.
Changing Configuration
To alter the configuration of your MFC project to use unmanaged code, change the following items in the Configuration Properties dialog box.
General - Use Managed Extensions = YES
C/C++ - General - Debug Information Format = Program Database (/Zi)
C/C++ - General - Compile As Managed = Assembly Support (/clr)
C/C++ - Code Generation - Enable Minimal Rebuild = No
C/C++ - Code Generation - Basic Runtime Checks = Default
The /clr compiler option provides module-level control for compiling functions either as managed or unmanaged. Now you must add the following code wherever you want to use managed code. If you want use managed code in several classes of your project it is better that you add this code to the stdafx.h file.
#pragma managed
#using
#using
#using
#using namespace System;
#using namespace System::Data;
#using namespace System::Data::OleDb;
The managed pragma enables function-level control for compiling functions as managed. An unmanaged function will be compiled for the native platform, and execution of that portion of the program will be passed to the native platform by the common language runtime.
Because we are using ADO.NET in our project so we have to add System::Data and since we want to use the MS Access database we have added System::Data::OleDb.
__gc Pointers in Unmanaged Classes
To declare a managed pointer as member in a class we must use __gc pointers. It is illegal to declare a member of an unmanaged class to have __gc pointer type. In order to point to a managed object from the C++ heap, the header file vcclr.h provides the type-safe wrapper template gcroot. Use of this template allows the programmer to embed a virtual __gc pointer in an unmanaged class and treat it as if it were the underlying type. The header file vcclr.h is included in VS.NET by default and you don’t need to include it to your application. Anyway this file can be found in the \Microsoft Visual Studio .NET\Vc7\include directory.
Therefore for declaring pointers of OleDB classes as members we must writing something like this.
gcroot
gcroot
gcroot
Writing Managed Code
Now it is time to write managed code in an unmanaged function.
Collapse
#pragma push_macro("new")
#undef new
try
{
m_OleDbConnection = new OleDbConnection(
S"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\test.mdb"
);
m_OleDbConnection->Open(); // Open up the connection
m_OleDb = new OleDbCommand(S"select * from Persons", m_OleDbConnection);
m_Reader = m_OleDb->ExecuteReader();
int count = 0;
while (m_Reader->Read())
{
AddToList(count,m_Reader->get_Item("First Name")->ToString(),
m_Reader->get_Item("Last Name")->ToString(),
m_Reader->get_Item("Phone Number")->ToString()
);
count++;
}
}
catch(Exception *e)
{
AfxMessageBox(CString(e->ToString()));
}
__finally
{
m_Reader->Close();
m_OleDbConnection->Close();
}
#pragma pop_macro("new")
the #pragma push_macro("new"), #undef new and #pragma pop_macro("new") are used when your project is in debug mode. Otherwise you will get errors saying placement arguments not allowed while creating instances of managed classes.
This was a small sample that indicates how we can use .NET library in MFC based projects. By following this sample You can write more complicated projects and using more benefits of .NET. It is easy to cope with and entirely feasible to extend your own MFC applications with managed code.
About the Author
Labels: Interoperability
| Posted at |
☆ |
__gc and __nogc:
/clr, the classes don't automatically become managed and are marked __nogc;If your class does meet the requirements of the CLR, however, you can make your class managed by marking it with the __gc modifier to indicate that it is a garbage-collected class, or the __value modifier to indicate that it is a CTS value type.Enable function-level control for compiling functions as managed or unmanaged.
They tell compiler the following code is managed or unmanaged;
Labels: Interoperability
| Posted at |
☆ |
|
Labels: C# , Serialization
| Posted at |
☆ |
By Sacha Barber
Introduction
There is not really much to say about this article except that it shows how to automate Microsoft Excel through C#. More precisley, what it shows is how to export a C# GridView/DataView to Excel, and how to format the resultant Excel spreadsheet cells. It also shows how to place WordArt and how to use a custom template, where a few values are filled in at predetermined cell positions.
The Associated GUI
Normally, I would say not to worry too much about the GUI, but in this one, there are some nice features like how do use the BackgroundWorker object and how to use Invoke to marshal threads to allow different threads to change GUI component properties. It also shows the use of anonomous delegates which is something new to .NET (old news in Java).
This is all really covered in the following areas.
//need to call InvokeRequired to check if thread
//need marshalling, to get the thread onto
//the same thread as the thread who owns the controls
if (this.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
progressBar1.Value = e.ProgressValue;
}));
}
else
{
progressBar1.Value = e.ProgressValue;
}
In this snippet, we can see two of the three points mentioned above (although this is nothing to do with Excel automation, it is code of interest I hope), but the export2Excel object raises an event, which is meant to update the GUI. But the GUI component handles were created on a different thread, so we need to use Invoke to get onto the correct thread to change the GUI component properties or call their methods, so why not chuck in an anonomous delegate to demo this.
The code is probably the best place to look at this, for a complete understanding. This article is really about the excel automation so lets stick to that. I just thought I mention this stuff here.
Excel office automation
So what does this code do??
Well it does two things:
* It exports a GridView to Excel and colors cells, applies formatting etc., and also adds some WordArt. All the normal Excel stuff that one might want to do. It then saves this as a new Excel document, as specified by the user.
* It also uses a premade template and puts some values in the correct cell positions and saves that as a new Excel document, as specified by the user.
Using the code
The demo project attached actually contains a Visual Studio 2005 solution, with the following three classes:
Program class
This is the main entry point into the GridviewToExcel application. Essentially, all this class does is create a new Form1 object.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace GridviewToExcel
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1 class (Designer code not shown, see zip file)
Queries access database (part of the zip) to create a new GridView, and exports the data to a new Excel document, or creates a new Excel document from an existing template, based on what button was clicked.
Collapse
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.IO;
namespace GridviewToExcel
{
public partial class Form1 : Form
{
//instance fields
private export2Excel export2XLS;
private DataSet _dataSet;
public Form1()
{
InitializeComponent();
}
//load the gridview using the local access database
private void Form1_Load(object sender, EventArgs e)
{
Directory.SetCurrentDirectory(Application.StartupPath +
@"..\..\..\");
String accessPath = Directory.GetCurrentDirectory() +
@"\Northwind.mdb";
// Set the connection and sql strings
// assumes your mdb file is in your root
string connString =
@"Provider=Microsoft.JET.OLEDB.4.0;data source=" + accessPath;
string sqlString = "SELECT * FROM customers";
OleDbDataAdapter dataAdapter = null;
_dataSet = null;
try
{
// Connection object
OleDbConnection connection = new OleDbConnection(connString);
// Create data adapter object
dataAdapter = new OleDbDataAdapter(sqlString, connection);
// Create a dataset object and fill with data
// using data adapter's Fill method
_dataSet = new DataSet();
dataAdapter.Fill(_dataSet, "customers");
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show("Problem with DB access-\n\n connection: "
+ connString + "\r\n\r\n query: " + sqlString
+ "\r\n\r\n\r\n" + ex.ToString());
this.Close();
return;
}
DataView dvCust = _dataSet.Tables["customers"].DefaultView;
dg1.DataSource = dvCust;
}
//Do a straight export to a new Excel document
//of the gridviews grid data
private void btn2Excel_Click(object sender, EventArgs e)
{
//show a file save dialog and ensure the user selects
//correct file to allow the export
saveFileDialog1.Filter = "Excel (*.xls)|*.xls";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if (!saveFileDialog1.FileName.Equals(String.Empty))
{
FileInfo f = new FileInfo(saveFileDialog1.FileName);
if (f.Extension.Equals(".xls"))
{
StartExport(saveFileDialog1.FileName);
}
else
{
MessageBox.Show("Invalid file type");
}
}
else
{
MessageBox.Show("You did pick a location " +
"to save file to");
}
}
}
//starts the export to new excel document
//@param filepath : the file to export to
private void StartExport(String filepath)
{
btn2Excel.Enabled = false;
btnUseTemplate.Enabled = false;
//create a new background worker, to do the exporting
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
bg.RunWorkerAsync(filepath);
//create a new export2XLS object, providing
//DataView as a input parameter
export2XLS = new export2Excel();
export2XLS.prg +=
new export2Excel.ProgressHandler(export2XLS_prg);
}
//do the new excel document work using the background worker
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
//get the Gridviews DataView
DataView dv = _dataSet.Tables["customers"].DefaultView;
//Pass the path and the sheet to use
export2XLS.ExportToExcel(dv, (String)e.Argument, "newSheet1");
}
//Do a export to a new Excel document,
//with the use of a custom template
private void btnUseTemplate_Click(object sender, EventArgs e)
{
//show a file save dialog and ensure the user selects
//correct file to allow the export
saveFileDialog1.Filter = "Excel (*.xls)|*.xls";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if (!saveFileDialog1.FileName.Equals(String.Empty))
{
FileInfo f = new FileInfo(saveFileDialog1.FileName);
if (f.Extension.Equals(".xls"))
{
StartExportUseTemplate(saveFileDialog1.FileName);
}
else
{
MessageBox.Show("Invalid file type");
}
}
else
{
MessageBox.Show("You did pick a location" +
" to save file to");
}
}
}
//Create a new excel document from a given template
//@param filepath : the file to export to
private void StartExportUseTemplate(String filepath)
{
btn2Excel.Enabled = false;
btnUseTemplate.Enabled = false;
//create a new background worker, to do the exporting
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(bg_DoWorkUseTemplate);
bg.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
bg.RunWorkerAsync(filepath);
//create a new export2XLS object, providing
//DataView as a input parameter
export2XLS = new export2Excel();
export2XLS.prg +=
new export2Excel.ProgressHandler(export2XLS_prg);
}
//Do the adding to custom template to create new excel document,
//work using the background worker
private void bg_DoWorkUseTemplate(object sender, DoWorkEventArgs e)
{
//create some data to whack in the template
String[,] templateValues = { { "task1",
"CompletedBy1", "CompletedDate1" },
{ "task2", "CompletedBy2", "CompletedDate2" }
};
//The template path to use
Directory.SetCurrentDirectory(Application.StartupPath +
@"..\..\..\");
String templatePath = Directory.GetCurrentDirectory() +
@"\TaskList.xlt";
//Pass the template path and the test values and fill
//the template
export2XLS.UseTemplate((String)e.Argument, templatePath,
templateValues);
}
//Update the progress bar with the a value
private void export2XLS_prg(object sender, ProgressEventArgs e)
{
//need to call InvokeRequired to check
//if thread need marshalling, to get the thread onto
//the same thread as the thread who owns the controls
if (this.InvokeRequired)
{
this.Invoke(new EventHandler(delegate
{
progressBar1.Value = e.ProgressValue;
}));
}
else
{
progressBar1.Value = e.ProgressValue;
}
}
//show a message to the user when the background worker has finished
//and re-enable the export buttons
private void bg_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
btn2Excel.Enabled = true;
btnUseTemplate.Enabled = true;
MessageBox.Show("Finished");
}
}
}
export2Excel class does the excel automation
This is where all the real office automation stuff occurs.
Collapse
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;
using System.Runtime.InteropServices; // For COMException
using System.Reflection; // For Missing.Value and BindingFlags
using System.Diagnostics; // to ensure EXCEL process is really killed
namespace GridviewToExcel
{
#region export2Excel CLASS
/// This class processes the DataView that it is provided and
/// Exports this DataView to an Excel document.
public class export2Excel
{
#region InstanceFields
//Instance Fields
public delegate void ProgressHandler(object sender,
ProgressEventArgs e);
public event ProgressHandler prg;
private DataView dv;
private Style styleRows;
private Style styleColumnHeadings;
private Microsoft.Office.Interop.Excel.Application EXL;
private Workbook workbook;
private Sheets sheets;
private Worksheet worksheet;
private string[,] myTemplateValues;
private int position;
#endregion
#region Constructor
//Constructs a new export2Excel object. The user must
//call the createExcelDocument method once a valid export2Excel
//object has been instantiated
public export2Excel()
{
}
#endregion
#region EXCEL : ExportToExcel
//Exports a DataView to Excel. The following steps are carried out
//in order to export the DataView to Excel
//Create Excel Objects
//Create Column & Row Workbook Cell Rendering Styles
//Fill Worksheet With DataView
//Add Auto Shapes To Excel Worksheet
//Select All Used Cells
//Create Headers/Footers
//Set Status Finished
//Save workbook & Tidy up all objects
//@param dv : DataView to use
//@param path : The path to save/open the EXCEL file to/from
//@param sheetName : The target sheet within the EXCEL file
public void ExportToExcel(DataView dv,string path, string sheetName)
{
try
{
//Assign Instance Fields
this.dv = dv;
#region NEW EXCEL DOCUMENT : Create Excel Objects
//create new EXCEL application
EXL = new Microsoft.Office.Interop.Excel.ApplicationClass();
//index to hold location of the requested sheetName
//in the workbook sheets
//collection
int indexOfsheetName;
#region FILE EXISTS
//Does the file exist for the given path
if (File.Exists(path))
{
//Yes file exists, so open the file
workbook = EXL.Workbooks.Open(path,
0, false, 5, "", "", false,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
"", true, false, 0, true, false, false);
//get the workbook sheets collection
sheets = workbook.Sheets;
//set the location of the requested sheetName to -1,
//need to find where
//it is. It may not actually exist
indexOfsheetName = -1;
//loop through the sheets collection
for (int i = 1; i <= sheets.Count; i++)
{
//get the current worksheet at index (i)
worksheet = (Worksheet)sheets.get_Item(i);
//is the current worksheet the sheetName
//that was requested
if (worksheet.Name.ToString().Equals(sheetName))
{
//yes it is, so store its index
indexOfsheetName = i;
//Select all cells, and clear the contents
Microsoft.Office.Interop.Excel.Range myAllRange =
worksheet.Cells;
myAllRange.Select();
myAllRange.CurrentRegion.Select();
myAllRange.ClearContents();
}
}
//At this point it is known that the sheetName
//that was requested
//does not exist within the found file,
//so create a new sheet within the
//sheets collection
if (indexOfsheetName == -1)
{
//Create a new sheet for the requested sheet
Worksheet sh = (Worksheet)workbook.Sheets.Add(
Type.Missing,
(Worksheet)sheets.get_Item(sheets.Count),
Type.Missing, Type.Missing);
//Change its name to that requested
sh.Name = sheetName;
}
}
#endregion
#region FILE DOESNT EXIST
//No the file DOES NOT exist, so create a new file
else
{
//Add a new workbook to the file
workbook =
EXL.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
//get the workbook sheets collection
sheets = workbook.Sheets;
//get the new sheet
worksheet = (Worksheet)sheets.get_Item(1);
//Change its name to that requested
worksheet.Name = sheetName;
}
#endregion
#region get correct worksheet index for requested sheetName
//get the workbook sheets collection
sheets = workbook.Sheets;
//set the location of the requested sheetName
//to -1, need to find where
//it is. It will definately exist now
//as it has just been added
indexOfsheetName = -1;
//loop through the sheets collection
for (int i = 1; i <= sheets.Count; i++)
{
//get the current worksheet at index (i)
worksheet = (Worksheet)sheets.get_Item(i);
//is the current worksheet the sheetName
//that was requested
if (worksheet.Name.ToString().Equals(sheetName))
{
//yes it is, so store its index
indexOfsheetName = i;
}
}
//set the worksheet that the DataView should
//write to, to the known index of the
//requested sheet
worksheet = (Worksheet)sheets.get_Item(indexOfsheetName);
#endregion
#endregion
// Set styles 1st
SetUpStyles();
//Fill EXCEL worksheet with DataView values
fillWorksheet_WithDataView();
//Add the autoshapes to EXCEL
AddAutoShapesToExcel();
//Select all used cells within current worksheet
SelectAllUsedCells();
try
{
workbook.Close(true, path, Type.Missing);
EXL.UserControl = false;
EXL.Quit();
EXL = null;
//kill the EXCEL process as a safety measure
killExcel();
// Show that processing is finished
ProgressEventArgs pe = new ProgressEventArgs(100);
OnProgressChange(pe);
MessageBox.Show("Finished adding " +
"dataview to Excel", "Info",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
catch (COMException cex)
{
MessageBox.Show("User closed Excel manually, " +
"so we don't have to do that");
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex.Message);
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex.Message);
}
}
#endregion
#region EXCEL : UseTemplate
//Exports a DataView to Excel. The following steps are carried out
//in order to export the DataView to Excel
//Create Excel Objects And Open Template File
//Select All Used Cells
//Create Headers/Footers
//Set Status Finished
//Save workbook & Tidy up all objects
//@param path : The path to save/open the EXCEL file to/from
public void UseTemplate(string path, string templatePath,
string[,] myTemplateValues)
{
try
{
this.myTemplateValues = myTemplateValues;
//create new EXCEL application
EXL = new Microsoft.Office.Interop.Excel.ApplicationClass();
//Yes file exists, so open the file
workbook = EXL.Workbooks.Open(templatePath,
0, false, 5, "", "", false,
Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
//get the workbook sheets collection
sheets = workbook.Sheets;
//get the new sheet
worksheet = (Worksheet)sheets.get_Item(1);
//Change its name to that requested
worksheet.Name = "ATemplate";
//Fills the Excel Template File Selected With A 2D Test Array
fillTemplate_WithTestValues();
//Select all used cells within current worksheet
SelectAllUsedCells();
try
{
workbook.Close(true, path, Type.Missing);
EXL.UserControl = false;
EXL.Quit();
EXL = null;
//kill the EXCEL process as a safety measure
killExcel();
// Show that processing is finished
ProgressEventArgs pe = new ProgressEventArgs(100);
OnProgressChange(pe);
MessageBox.Show("Finished adding test values to " +
"Template", "Info",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
catch (COMException)
{
Console.WriteLine("User closed Excel manually," +
" so we don't have to do that");
}
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex.Message);
}
}
#endregion
#region STEP 1 : Create Column & Row Workbook Cell Rendering Styles
//Creates 2 Custom styles for the workbook These styles are
// styleColumnHeadings
// styleRows
//These 2 styles are used when filling
//the individual Excel cells with the
//DataView values. If the current cell relates
//to a DataView column heading
//then the style styleColumnHeadings will be used
//to render the current cell.
//If the current cell relates to a DataView row
//then the style styleRows will
//be used to render the current cell.
private void SetUpStyles()
{
// Style styleColumnHeadings
try
{
styleColumnHeadings = workbook.Styles["styleColumnHeadings"];
}
// Style doesn't exist yet.
catch
{
styleColumnHeadings =
workbook.Styles.Add("styleColumnHeadings", Type.Missing);
styleColumnHeadings.Font.Name = "Arial";
styleColumnHeadings.Font.Size = 14;
styleColumnHeadings.Font.Color =
(255 << 16) | (255 << 8) | 255;
styleColumnHeadings.Interior.Color =
(0 << 16) | (0 << 8) | 0;
styleColumnHeadings.Interior.Pattern =
Microsoft.Office.Interop.Excel.XlPattern.xlPatternSolid;
}
// Style styleRows
try
{
styleRows = workbook.Styles["styleRows"];
}
// Style doesn't exist yet.
catch
{
styleRows = workbook.Styles.Add("styleRows", Type.Missing);
styleRows.Font.Name = "Arial";
styleRows.Font.Size = 10;
styleRows.Font.Color = (0 << 16) | (0 << 8) | 0;
styleRows.Interior.Color =
(192 << 16) | (192 << 8) | 192;
styleRows.Interior.Pattern =
Microsoft.Office.Interop.Excel.XlPattern.xlPatternSolid;
}
}
#endregion
#region STEP 2 : Fill Worksheet With DataView
//Fills an Excel worksheet with the values contained in the DataView
//parameter
private void fillWorksheet_WithDataView()
{
position = 0;
//Add DataView Columns To Worksheet
int row = 1;
int col = 1;
// Loop thought the columns
for (int i = 0; i <>
{
fillExcelCell(worksheet, row, col++,
dv.Table.Columns[i].ToString(),
styleColumnHeadings.Name);
}
//Add DataView Rows To Worksheet
row = 2;
col = 1;
for (int i = 0; i <>
{
for (int j = 0; j <>
{
fillExcelCell(worksheet, row, col++, dv[i][j].ToString(),
styleRows.Name);
}
col = 1;
row++;
position = (100 / dv.Table.Rows.Count) * row + 2;
ProgressEventArgs pe = new ProgressEventArgs(position);
OnProgressChange(pe);
}
}
#endregion
#region STEP 3 : Fill Individual Cell and Render Using Predefined Style
//Formats the current cell based on the Style setting parameter name
//provided here
//@param worksheet : The worksheet
//@param row : Current row
//@param col : Current Column
//@param Value : The value for the cell
//@param StyleName : The style name to use
private void fillExcelCell(Worksheet worksheet, int row, int col,
Object Value, string StyleName)
{
Range rng = (Range)worksheet.Cells[row, col];
rng.Select();
rng.Value2 = Value.ToString();
rng.Style = StyleName;
rng.Columns.EntireColumn.AutoFit();
rng.Borders.Weight = XlBorderWeight.xlThin;
rng.Borders.LineStyle = XlLineStyle.xlContinuous;
rng.Borders.ColorIndex = XlColorIndex.xlColorIndexAutomatic;
}
#endregion
#region STEP 4 : Add Auto Shapes To Excel Worksheet
//Add some WordArt objecs to the Excel worksheet
private void AddAutoShapesToExcel()
{
//Method fields
float txtSize = 80;
float Left = 100.0F;
float Top = 100.0F;
//Have 2 objects
int[] numShapes = new int[2];
Microsoft.Office.Interop.Excel.Shape[] myShapes =
new Microsoft.Office.Interop.Excel.Shape[numShapes.Length];
try
{
//loop through the object count
for (int i = 0; i < numShapes.Length; i++)
{
//Add the object to Excel
myShapes[i] =
worksheet.Shapes.AddTextEffect(
MsoPresetTextEffect.msoTextEffect1, "DRAFT",
"Arial Black", txtSize, MsoTriState.msoFalse,
MsoTriState.msoFalse, (Left * (i * 3)), Top);
//Manipulate the object settings
myShapes[i].Rotation = 45F;
myShapes[i].Fill.Visible =
Microsoft.Office.Core.MsoTriState.msoFalse;
myShapes[i].Fill.Transparency = 0F;
myShapes[i].Line.Weight = 1.75F;
myShapes[i].Line.DashStyle =
MsoLineDashStyle.msoLineSolid;
myShapes[i].Line.Transparency = 0F;
myShapes[i].Line.Visible =
Microsoft.Office.Core.MsoTriState.msoTrue;
myShapes[i].Line.ForeColor.RGB =
(0 << 16) | (0 << 8) | 0;
myShapes[i].Line.BackColor.RGB =
(255 << 16) | (255 << 8) | 255;
}
}
catch (Exception ex)
{
}
}
#endregion
#region STEP 5 : Select All Used Cells
//Selects all used cells for the Excel worksheet
private void SelectAllUsedCells()
{
Microsoft.Office.Interop.Excel.Range myAllRange = worksheet.Cells;
myAllRange.Select();
myAllRange.CurrentRegion.Select();
}
#endregion
#region STEP 6 : Fill Template With Test Values
//Fills the Excel Template File Selected With
//A 2D Test Array parameter
private void fillTemplate_WithTestValues()
{
//Initilaise the correct Start Row/Column to match the Template
int StartRow = 3;
int StartCol = 2;
position=0;
// Display the array elements within the Output
// window, make sure its correct before
for (int i=0; i <= myTemplateValues.GetUpperBound(0); i++)
{
//loop through array and put into EXCEL template
for (int j = 0 ;
j <= myTemplateValues.GetUpperBound(1) ;
j++)
{
//update position in progress bar
position = (100 / myTemplateValues.Length) * i;
ProgressEventArgs pe = new ProgressEventArgs(position);
OnProgressChange(pe);
//put into EXCEL template
Range rng = (Range)worksheet.Cells[StartRow,StartCol++];
rng.Select();
rng.Value2 = myTemplateValues[i,j].ToString();
rng.Rows.EntireRow.AutoFit();
}
//New row, so column needs to be reset
StartCol=2;
StartRow++;
}
}
#endregion
#region Kill EXCEL
//As a safety check go through all processes and make
//doubly sure excel is shutdown. Working with COM
//have sometimes noticed that the EXL.Quit() call
//doesn't always do the job
private void killExcel()
{
try
{
Process[] ps = Process.GetProcesses();
foreach (Process p in ps)
{
if (p.ProcessName.ToLower().Equals("excel"))
{
p.Kill();
}
}
}
catch (Exception ex)
{
MessageBox.Show("ERROR " + ex.Message);
}
}
#endregion
#region Events
/// Raises the OnProgressChange event for the parent form.
public virtual void OnProgressChange(ProgressEventArgs e)
{
if (prg != null)
{
// Invokes the delegates.
prg(this, e);
}
}
#endregion
}
#endregion
#region ProgressEventArgs CLASS
/// Provides the ProgressEventArgs
public class ProgressEventArgs : EventArgs
{
#region Instance Fields
//Instance fields
private int prgValue = 0;
#endregion
#region Public Constructor
/// Constructs a new ProgressEventArgs object
/// using the parameters provided
/// @param prgValue : new progress value
public ProgressEventArgs(int prgValue)
{
this.prgValue = prgValue;
}
#endregion
#region Public Methods/Properties
/// Returns the progress value
public int ProgressValue
{
get { return prgValue; }
}
#endregion
}
#endregion
}
Labels: Export
| Posted at |
☆ |
"We'll start to see more and more organizations scaling Agile approaches with the proven strategies contained in older methodologies such as Rational Unified Process (RUP) as well as new methods such as Agile Modeling (AM)," Ambler said. Test-driven development (TDD) in particular will be adopted, "particularly when people realize how to scale it with Agile Model Driven Development (AMDD)." |
Labels: Others
| Posted at |
☆ |
Custom DataGrid Paging at the Server
by Peter A. Bromberg, Ph.D.
Peter Bromberg
"We are all acting like there isn't an elephant in the room."
- Sen. Joe Biden, at opening of Samuel Alito Confirmation Hearings
The ASP.NET DataGrid's built-in Paging capabilty is a great feature, and it's relatively easy to learn to use. However, as most developers are aware, the downside is that this paging is done based on bringing back the entire resultset every time a new page is requested. Of course, you can cache the resultset to cut down on bandwidth.
But what if you have 50,000 or 100,000 rows that you need to offer your user to page through? That's a lot of baggage to bring along! Certainly you do not want to load and / or cache all this data when, for example, your user is really only looking at ten rows at a time on a paged DataGrid. What you really want to do is show them the total number of pages in a standard DataGrid Pager Bar arrangement, and send them only the ten rows representing the actual page that they have selected to see.
The answer to this question is to use Custom Paging. The DataGrid has two features that you need to use for this:
1) Set the AllowCustomPaging property to "true".
2) Set the VirtualItemCount to the total number of available rows from each query so that the Pager knows what to display on the Pager Bar.
The final piece of the equation is to have a stored procedure that can dynamically select the correct rows and only send back "one page" worth of rows, whatever your PageSize happens to be.
Fortunately, the code to implement custom paging in an ASP.NET page is trivial. The stored procedures necessary for this arrangement are not. However, there is a broad range of solutions and my philosophy is "keep it simple". So I will present my own version of a dynamically created stored proc to handle this where you can pass in parameters consisting of the table's PrimaryKey, the table name, the Current Page index, the number of rows per Page, and finally, if desired, a custom "WHERE" clause of your choosing. The stored proc will take care of the rest.
My version is a pretty short sproc - a lot shorter and simpler than many you will find. However, you may find that you need more, and if you do, then at least this solution will give you the basis from which to understand what you need for your custom solution.
What I'll do here is show the stored proc, fashioned to get rows from the Northwind Orders table, which almost everyone has handy. However, it can be used or modified to work with most any table. If you need rows from more than one table, then you'll need to modify this to include the proper JOIN syntax.
Now, the sproc:
CREATE PROC dbo.GetPagedData
@pageSize int,
@tablename varchar(100) ,
@PrimaryKey varchar(50) ,
@CurrentPage int ,
@WhereClause varchar(250)
AS
if(@WhereClause IS NULL or @WhereClause='') Set @WhereClause=' 1=1 '
Declare @sql nvarchar(4000)
declare @numrecs int
Set @numrecs=@pageSize*@currentPage
set @sql='SELECT TOP ' + cast(@pageSize as varchar(5))+' * FROM ' +@tablename
Set @sql =@sql + ' WHERE '+cast(@PrimaryKey as varchar(50))+ ' NOT IN (SELECT TOP '
set @sql=@sql+ cast(@numrecs as varchar(5))
set @sql=@Sql+ ' ' +@primarykey +' FROM ' +@tableName + ' WHERE '+@whereClause +
' ORDER BY ' +cast(@primarykey as varchar(50)) +' ) '
set @Sql=@sql + ' AND '+ @whereClause
Set @Sql=@Sql + ' ORDER BY '+cast(@primarykey as varchar(50))
--print @sql
EXEC sp_executeSql @sql
Set @sql='Select count(*) FROM ' +@tablename + ' WHERE ' +@whereclause
EXEC sp_executeSql @sql
As can be easily seen, all this sproc does is construct dynamic SQL to return @pageSize number of rows using the TOP Keyword along with a limiting SubSelect which also uses the TOP keyword, and it applies your where clause, if any. Finally it does a second Select to get the total number of rows that match the query. I use sp_ExecuteSql as it is more efficient. You can even see the commented "print @sql" line I used to ensure my dynamic sql turned out OK. I really don't like dynamic Sql, but like any other evil thing, it has its uses. Pretty simple!
The only other thing we need to look at is the codebehind for the page, which is also surprisingly simple:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.ApplicationBlocks.Data;
namespace PagedData
{
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DataGrid DataGrid1;
protected int curPageSize =0;
private void Page_Load(object sender, System.EventArgs e)
{
curPageSize=this.DataGrid1.PageSize;
// if we just loaded the page for the first time, display page 1 of our data:
if(!IsPostBack)
BindGrid(curPageSize,1);
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.DataGrid1.PageIndexChanged+=new System.Web.UI.WebControls.DataGridPageChangedEventHandler(
this.DataGrid1_PageIndexChanged);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void BindGrid(int pageSize, int pageNumber)
{
string cnString= System.Configuration.ConfigurationSettings.AppSettings["connectionString"];
/* sproc parameters: @pageSize int,
@tablename varchar(100),
@PrimaryKey varchar(50),
@CurrentPage int,
@WhereClause varchar(250) */
string tableName = "orders";
string primaryKey="orderid";
string whereClause="orderDate >='8/1/1997'";
// string whereClause=String.Empty ; // null string for no "where" clause
object[] parms = new object[] {pageSize,tableName,primaryKey, pageNumber, whereClause};
DataSet ds= SqlHelper.ExecuteDataset(cnString,"dbo.GetPagedData",parms);
// Our second datatable has 1 row, 1 column - the number of total rows available to page
// with custom paging, that gets assigned to the VirtualItemCount property:
this.DataGrid1.VirtualItemCount =Convert.ToInt32(ds.Tables[1].Rows[0][0]);
this.DataGrid1.DataSource=ds.Tables[0];
DataGrid1.CurrentPageIndex =pageNumber;
DataGrid1.DataBind();
}
private void DataGrid1_PageIndexChanged(object source, System.Web.UI.WebControls.DataGridPageChangedEventArgs e)
{
// user clicks forward or back, just call BindGrid with the NewPageIndex:
BindGrid(this.curPageSize , e.NewPageIndex);
}
}
}
How it works:
The main part of the working code is the BindGrid method, which accepts a PageSize and the expected pageNumber (or PageIndex, in DataGridSpeak). It puts together the parameter list for the Stored Proc of PageSize, TableName, PrimaryKey (the column name), CurrentPage, and any Where Clause, then calls the SqlHelper ExecuteDataSet method to get the DataSet, which contains two tables: the first is our "Page" of data, and the second is a single row and column containing the count of total records that can be retrieved for this particular query. This is needed to store in the grid's VirtualItemCount, which it uses to construct the correct Pager Bar elements.
And of course, I use the MS Data Access Application Block "SqlHelper Class" for my data access. Two lines of code to make a stored proc call with parameters, and your SqlParameters get cached automatically for a performance boost to boot! Hey, if you can write better "Best Practices" data access code than this, knock yourself out - I can't!
Whenever a user clicks on a numbered page in the PagerBar, the PageIndexChanged event is fired, and it simply calls BindGrid again, supplying the curPageSize of the grid on the page, and the NewPageIndex. That's all there is to it! You can find a lot of solutions for server-side DataGrid paging. Most of them will be nowhere near as simple and easy to understand as this one!
You will note that I have left out exception handling. The sole purpose of this omission is to keep the code as simple and easy - to - understand as possible for the purpose of a tutorial. In "real life" you should always have good quality exception checking that looks for specific exception types (e.g. "SqlException") whereever in your code anything could possibly go wrong. And, you don't just catch an exception -- you make a business decision -- should I allow the app to continue, show a message to the user, or do I need to terminate the app?
Hope this is helpful to you in your travails.
Download the VS.NET 2003 Solution that accompanies this article
Labels: Custom Paging , Query Optimization