ADO.NET กับ Excel สอบถามการเขียนโปรแกรมติดต่อกับ Excel ในการดึงเอาชื่อ Sheet ออกมาครับ
ผมมีปัญหากับการเขียนโปรแกรมติดต่อกับ Excel 2003 กับ 2007 ครับ พยายามหาข้อมูลแล้วทั้งเว็บไทยเว็บนอก ไม่รู้ว่าใช้ Keyword ไม่ถูกหรือยังไง เพราะหายังไงก็หาไม่เจอ ปัญหาที่พบจะเป็นส่วนของการดึงชื่อ Sheet ที่มีอยู่ในไฟล์ Excel ครับ
วิธีที่ผมใช้นั้น จะใช้ตามเว็บนี้เลยครับ http://www.dotneter.com/get-excel-sheet-names-using-c
แต่ข้อมูล Sheet ที่ได้มานั้นมันมีค่าขยะหรือ Sheet อื่นๆ ผมไม่เห็นว่ามันมีอยู่ใน ไฟล์ Excel มาด้วย
เช่น
ในไฟล์ Excel เวลาเปิดดูจะเห็นมี Sheet1 และ Sheet2
แต่พอเขียนโปรแกรมแล้ว Sheet ที่ได้มากลับมี 4 ค่า คือ
Sheet1$ , Sheet1$Print_Titles , Sheet2, Sheet2_
บ้างไฟล์ก็ได้เป็นแบบนี้ครับ
เปิดใน Excel เห็น 2 Sheet คือ Sheet1 , Sheet2
แต่พอเขียนโปรแกรมแล้ว ได้ชื่อ Sheet มา 6 ชื่อเลยคือ
Code
_xlnm#Print_Titles , _xlnm#_FilterDatabase , _xlnm#Criteria , _xlnm#Extract , Sheet1$ , Sheet2$
บ้างไฟล์ ก็ไม่มีปัญหานะครับเปิดใน Excel เห็น 2 Sheet ในโปรแกรมก็เจอแค่ Sheet1$ และ Sheet2$
ไม่ทราบว่า พอจะมีวิธีแนะนำไหมครับ ผมพยายามหาในเน็ตแล้วแต่ยังไม่เจอวิธีครับ ไม่รู้ว่าผิดตรงไหน หรือว่ามันต้องไปตั้งค่าอะไรใน Excel หรือเปล่า พอดีไฟล์ Excel ที่ได้มานั้นเ็ป็นของลูกค้านะครับ
รบกวนพี่ๆ แนะนำด้วยครับTag : .NET, Win (Windows App), C#, VS 2010 (.NET 4.x)
ประวัติการแก้ไข 2012-06-15 17:21:09
Date :
2012-06-15 17:19:19
By :
Nameless
View :
4175
Reply :
11
คุณลองแปลงให้เป็น Version 2003 (.xls) แล้วลองดูใหม่ครับ
Date :
2012-06-16 10:56:00
By :
mr.win
รองแล้วครับ ก็ยังเจอปัญหาเหมือนเดิมครับ
รองนำไฟล์จาก 2007(.xlsx) แปลงเป็น 2003(.xls) และ รองจากไฟล์ 2003(.xls) แปลงเป็น 2007(.xlsx) แล้วก็ยังเจอเหมือนเดิมครับ
ไฟล์ 2003(.xls) แปลงเป็น 2007(.xlsx) จะได้ Sheet พวกนี้มาอะครับ _xlnm#Print_Titles , _xlnm#_FilterDatabase , _xlnm#Criteria , _xlnm#Extract ไม่รู้มาจากไหน
ส่วน 2007(.xlsx) แปลงเป็น 2003(.xls) จะได้พวก Print_Titles หรือ _ ต่อท้ายมาเช่น ชื่อจริงๆ จะเป็น Sheet1$ แต่จะไม่ได้แค่ Sheet1$ อย่างเดียว จะมี Sheet1$Print_Titles มาด้วย ไม่รู้มาจากไหน
Date :
2012-06-16 21:39:17
By :
Nameless
ติดต่อ [email protected] ครับ ส่งรายละเอียดมา หรือไม่ก็แอดเอ็มมาคุยกัน
Date :
2012-06-16 22:10:27
By :
Projectsup
ขอบคุณ Projectsup มากครับ
ผม add ทาง msn ไปแล้วนะครับ ยังไงขอคำแนะนำด้วยครับ
Date :
2012-06-16 23:03:32
By :
Nameless
ลองใช้การอ่านผ่าน Excel.Application ดูน่ะครับ
Date :
2012-06-17 07:34:08
By :
mr.win
Code (C#)
protected void Page_Load(object sender, EventArgs e)
{
GetExcelSheetNames("C:\\test.xls");
}
private String[] GetExcelSheetNames(string excelFile)
{
OleDbConnection objConn = null;
System.Data.DataTable dt = null;
try
{
// Connection String. Change the excel file to the file you
// will search.
String connString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + excelFile + ";Extended Properties=Excel 8.0;";
// Create connection object by using the preceding connection string.
objConn = new OleDbConnection(connString);
// Open connection with the database.
objConn.Open();
// Get the data table containg the schema guid.
dt = objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
String[] excelSheets = new String[dt.Rows.Count];
int i = 0;
// Add the sheet name to the string array.
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
DropDownList1.Items.Add(row["TABLE_NAME"].ToString());
i++;
}
return excelSheets;
}
catch (Exception ex)
{
return null;
}
finally
{
// Clean up.
if (objConn != null)
{
objConn.Close();
objConn.Dispose();
}
if (dt != null)
{
dt.Dispose();
}
}
}
Date :
2012-06-18 00:06:22
By :
bangbang111
ถ้าได้ยังไงก็ลองโพสไว้ด้วยก็ดีครับ
Date :
2012-06-18 06:03:09
By :
mr.win
ได้แล้วครับ ขอบคุณทุกท่านมากที่มาให้คำแนะนำครับ สรุปผมไมไ่ด้เปลี่ยนไปใช้ Excel.Application อย่างที่พี่ mr.win และ พี่ pStudio แนะนำ เนื่องจากเครื่องลูกค้าที่เอาไปลงนั้นมีทั้ง version 2003 และ 2007 ไม่เหมือนกัน เลยกลัวว่าถ้าเปลี่ยนไปใช้แบบนั้นแล้วจะต้องแก้ไขเยอะ อีกอย่างถ้าใช้แบบที่ใช้อยู่เวลาไปติดตั้งไม่ต้องกังวลเรื่อง Library ของ MS office เลยเป็น version ไหน แค่ลง .net framework version เดียวกับที่เราใช้ก็สามารถใช้งานได้เลย
หลักการที่ใช้แก้นั้น คือตรวจสอบชื่อ Sheet ที่ได้มาครับ โดย
1. ตรวจสอบจากอักษร $ ก่้อน เพราะจะติดมากับชื่อ Sheet ทุกครั้งที่ได้มา จะแก้ปัญหาค่าที่ได้มาเป็นแบบนี้ได้ _xlnm#Print_Titles , _xlnm#_FilterDatabase , _xlnm#Criteria , _xlnm#Extract
2. แต่ทำแค่นั้นก็ยังผิดอยู่เนื่องจาก อาจจะได้ข้อมูลที่เป็นลักษณะแบบนี้อยู่ Sheet1$Print_Titles , Sheet2$_ ด้วยเหตุนี้ก็เลือกเขียนฟังก์ชันให้ตัดตัวอักษรหลัง $ ตัวสุดท้ายทิ้งไป
3. พอทำขั้นตอนที่ 2 แล้ว อาจจะได้ชื่อ Sheet ซ้ำกันออกมาอีก ตรงส่วนนี้ก็แก้ไขโดยการตัดคำซ้ำออก เท่านี้ก็เรียบร้อยครับ
ผลที่ได้เป็นแบบนี้ครับ ในส่วนของการ Connect ก็ตามที่พี่ bangbang111 เอามาลงเลยครับ
Code (C#)
private List<string> GetExcelSheetNames()
{
DataTable dt = null;
try
{
if (conn.State == ConnectionState.Open) conn.Close();
conn.Open();
// Get the data table containg the schema guid.
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
List<string> excelSheets = new List<string>(dt.Rows.Count);
int i = 0;
foreach (DataRow row in dt.Rows)
{
if (row["TABLE_NAME"].ToString().Contains("$"))//checks whether row contains '_xlnm#_FilterDatabase' or sheet name(i.e. sheet name always ends with $ sign)
{
if (row["TABLE_NAME"] != null)
{
excelSheets.Add(GetSheetName(row["TABLE_NAME"].ToString()));
}
}
i++;
}
excelSheets = excelSheets.Distinct().ToList();
return excelSheets;
}
catch (Exception ex)
{
return null;
}
}
private string GetSheetName(string str)
{
int use = 0;
int len = str.Length;
// Find last position of "$"
for (int i = 0; i < len; i++)
{
if (str.Substring(i, 1) == "$") use = i;
}
string tmp;
if (use == 0)
{ tmp = str; }
else
{ tmp = str.Substring(0, use + 1); }
return tmp;
}
ออกจะดูถึกๆ ไปหน่อยนะครับ แต่ก็โพสไว้ เผื่อท่านใดเจอปัญหาเดียวกันครับ
จากที่รองแ้ล้วก็กันได้ครบเงื่อนไขที่เจอครับ หากท่านใดเห็นว่าตรงไหนสามารถเปลี่ยนให้มันดีกว่านี้ได้ก็แนะนำได้ครับ
ประวัติการแก้ไข 2012-06-18 22:31:11
Date :
2012-06-18 18:13:34
By :
Nameless
เยี่ยมครับ สำหรับการแชร์คำตอบ
อันนี้แปลงเป็น VB.NET ให้ สำหรับคนที่ต้องการ VB.NET
Code (VB.NET)
Private Function GetExcelSheetNames() As List(Of String)
Dim dt As DataTable = Nothing
Try
If conn.State = ConnectionState.Open Then
conn.Close()
End If
conn.Open()
' Get the data table containg the schema guid.
dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
If dt Is Nothing Then
Return Nothing
End If
Dim excelSheets As New List(Of String)(dt.Rows.Count)
Dim i As Integer = 0
For Each row As DataRow In dt.Rows
If row("TABLE_NAME").ToString().Contains("$") Then
'checks whether row contains '_xlnm#_FilterDatabase' or sheet name(i.e. sheet name always ends with $ sign)
If row("TABLE_NAME") IsNot Nothing Then
excelSheets.Add(GetSheetName(row("TABLE_NAME").ToString()))
End If
End If
i += 1
Next
excelSheets = excelSheets.Distinct().ToList()
Return excelSheets
Catch ex As Exception
Return Nothing
End Try
End Function
Private Function GetSheetName(str As String) As String
Dim use As Integer = 0
Dim len As Integer = str.Length
' Find last position of "$"
For i As Integer = 0 To len - 1
If str.Substring(i, 1) = "$" Then
use = i
End If
Next
Dim tmp As String
If use = 0 Then
tmp = str
Else
tmp = str.Substring(0, use + 1)
End If
Return tmp
End Function
Date :
2012-06-19 06:22:15
By :
mr.win
Load balance : Server 01