求助:C# 用OleDb读取Excel内容不全??

琴弦里的海 2014-07-16 11:23:54
本人在做个考试系统,试题导入题库时出现这样情况:
用OleDb进行Excel内容导入数据库,在用OleDb读取数据时发现有些字符串过长时读取不全,比如:
Excel单元格内容:上海,简称“沪”或“申”,中国第一大城市,中华人民共和国直辖市之一,中国国家中心城市,中国的经济、金融中心,繁荣的国际大都市,拥有中国大陆首个自贸区“中国(上海)自由贸易试验区”。
上海地处长江入海口,东向东海,隔海与日本九州岛相望,南濒杭州湾,西与江苏、浙江两省相接,共同构成以上海为龙头的中国最大经济区“长三角经济圈”。上海拥有深厚的近代城市文化底蕴和众多历史古迹,江南的吴越传统文化与各地移民带入的多样文化相融合,形成了特有的海派文化。2010年成功举办了2010年世界博览会。

但是读取到的字符串只有:上海,简称“沪”或“申”,中国第一大城市,中华人民共和国直辖市之一,中国国家中心城市,中国的经济、金融中心,繁荣的国际大都市,拥有中国大陆首个自贸区“中国(上海)自由贸易试验区”。上海地处长江入海口,东向东海,隔海与日本九州岛相望,南濒杭州湾,西与江苏、浙江两省相接,共同构成以上海为龙头的中国最大经济区“长三角经济圈”。上海拥有深厚的近代城市文化底蕴


由于Excel里面内容不规则,所以不好用CSV格式,请问有谁碰到这样问题?具体如何解决的,谢谢!!!
...全文
764 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
lisweet_win 2015-10-17
  • 打赏
  • 举报
回复
我XXXXXXXXXX,终于解决了。 方法很简单。 前8行内 有一条记录 是大于 255 的就没有问题了。 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\14.0\Access Connectivity Engine\Engines\Excel 中的TypeGuessRows值来控制,默认是8。 如果前8行都是数字,那么ADO.NET扫描不会有问题; 如果前8行内的数据类型不一样,ADO.NET会采用一个通配的数据类型来匹配,通常为varchar或unicode varchar。但是如果前8行的数据都比较短小,使得ADO.NET选择匹配了varchar,那么就只能容下255个字符,而实际上却有可能是其它更大的类型。
lisweet_win 2015-10-17
  • 打赏
  • 举报
回复
问题 有没有新办法 解决?
  • 打赏
  • 举报
回复
引用 16 楼 han208 的回复:
我最终解决方法就是用直接OPEN的方式打开读单元格,不过这样的效率确实差啊!像上面兄弟说用NPOI来操作,我也想的,但是我就不想携带那些DLL文件,所以放弃了,目前只知道用这个方法保险点了,下次好好研究那个NPOI才行。
office 组件方式open,局限性更大,需要运行程序的电脑安装office相关组件
小K的大师兄 2014-07-30
  • 打赏
  • 举报
回复
引用 16 楼 han208 的回复:
我最终解决方法就是用直接OPEN的方式打开读单元格,不过这样的效率确实差啊!像上面兄弟说用NPOI来操作,我也想的,但是我就不想携带那些DLL文件,所以放弃了,目前只知道用这个方法保险点了,下次好好研究那个NPOI才行。
用ClosedXml也挺好的
於黾 2014-07-29
  • 打赏
  • 举报
回复
用OLEDB不是一样要携带DLL,有什么区别啊. 除非你是用ADODB,系统自带.
琴弦里的海 2014-07-29
  • 打赏
  • 举报
回复
我最终解决方法就是用直接OPEN的方式打开读单元格,不过这样的效率确实差啊!像上面兄弟说用NPOI来操作,我也想的,但是我就不想携带那些DLL文件,所以放弃了,目前只知道用这个方法保险点了,下次好好研究那个NPOI才行。
琴弦里的海 2014-07-29
  • 打赏
  • 举报
回复
引用 13 楼 huangcailian 的回复:
[quote=引用 11 楼 han208 的回复:] [quote=引用 7 楼 huangcailian 的回复:]

 public static void Main(string[] args)
        {
            QueryCSV();

            Console.ReadLine();
        }

        public static void QueryCSV()
        {
            //文件路径
            string tableName = "file.csv";
            string filePath = AppDomain.CurrentDomain.BaseDirectory;

            string pContent = string.Empty;

            OleDbConnection oledbConn = new OleDbConnection();
            OleDbCommand oledbCmd = new OleDbCommand();
            OleDbDataReader dataReader;
            try
            {
                //两种连接方式皆可
                //string strConnOledb = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
                string strConnOledb="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=";
                strConnOledb += filePath;
                strConnOledb += ";Extended Properties='Text;HDR=Yes;IMEX=1;'";

                oledbConn.ConnectionString = strConnOledb;
                oledbConn.Open();
                StringBuilder commandText = new StringBuilder("SELECT ");
                commandText.AppendFormat("* From {0}", tableName);
                oledbCmd.Connection = oledbConn;
                oledbCmd.CommandText = commandText.ToString();
                dataReader = oledbCmd.ExecuteReader();

                
                while (dataReader.Read())
                {
                    pContent = Convert.ToString(dataReader["content"]);
                }
                dataReader.Close();
            }
            catch (System.Exception ex)
            {
                oledbConn.Close();
            }
            finally
            {
                oledbConn.Close();
            }

            Console.WriteLine(pContent);
        }
完全没有问题,没有出现你说的那种情况。给你来个截图:
我明白你的意思,你试试在Excel前面十行的字符串不超过50个字符,然后在11行后的字符串超过260个字符,试试这样读取行不行?我试过的,在前面8行前,如果字符串不超过260个字符的,后面如果有超过就读取不全了,而如果在前8行有字符串超过260个字符,后面如果有同等长度字符串,还是能读全的。所以,我判断你的长字符串是放在EXCEL的前8行了,要不你按照我说的再试试?起码你也碰到这样问题了,提前为以后准备,呵呵[/quote] 我试了 也没出现你说的那种情况啊 难道是我试得不对 还有如果你真的出现这种情况 你把你Excel里面的内容用引号包起来在试试 [/quote] 估计是你输出的方式不一样吧,你可以像下面一位兄弟 geyewei 用textBox 或者richTextBOX输出看看
geyewei 2014-07-24
  • 打赏
  • 举报
回复
引用 10 楼 han208 的回复:
[quote=引用 8 楼 geyewei 的回复:] [quote=引用 6 楼 han208 的回复:] [quote=引用 3 楼 geyewei 的回复:] 我做了实验,能全取出来。VB2008。Excel2007 新建立一个Excel,单元格A1里面敲入字符串“aaa”,单元格A2里面贴入你的例子, 执行程序以后,VB窗体内的TextBox1里面的内容可以显示到 2010年成功举办了2010年世界博览会。 代码

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim frm As New OpenFileDialog
        With frm
            .ShowDialog()

            If .FileName <> "" Then
                Dim strCon As String = ""
                If .FileName.EndsWith(".xlsx") Then
                    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & .FileName & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes"";"
                Else
                    strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & .FileName & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
                End If

                Dim strSQL As String = "SELECT * FROM [Sheet1$]"

                Using adp As New Data.OleDb.OleDbDataAdapter(strSQL, strCon), dtbRet As New DataTable
                    adp.Fill(dtbRet)
                    TextBox1.Text = dtbRet.Rows(0)(0)
                End Using
            End If
        End With
    End Sub
上面单元内容是个例子,是表面这个情况,格子字数未足够长的,我自己求证过,如果字数超260就出现不全了,麻烦你再试试数字超过300的看看?[/quote] 试过了,我偷懒,把你的例子在A2单元格里复制粘贴了5遍,通过上面的代码还是能正常读出到最后一句话的,大概读出来1000多个字吧。[/quote] 我明白你的意思,你试试在Excel前面十行的字符串不超过50个字符,然后在11行后的字符串超过260个字符,试试这样读取行不行?我试过的,在前面8行前,如果字符串不超过260个字符的,后面如果有超过就读取不全了,而如果在前8行有字符串超过260个字符,后面如果有同等长度字符串,还是能读全的。所以,我判断你的长字符串是放在前8行了[/quote] 试过了,和你说的一致,现正查找原因中。我的重现步骤是:从A2单元格到A11单元格的内容为“这行的序号是1”。。。。“这行的序号是10”,A12单元格的内容是你的例子贴两遍。在这种感觉情况下,A12单元格的内容就取不全。而如果把A12单元格的内容粘贴到A2单元格的话,就所有的单元格的内容都能取出来。
小K的大师兄 2014-07-23
  • 打赏
  • 举报
回复
引用 11 楼 han208 的回复:
[quote=引用 7 楼 huangcailian 的回复:]

public static void Main(string[] args)
{
QueryCSV();

Console.ReadLine();
}

public static void QueryCSV()
{
//文件路径
string tableName = "file.csv";
string filePath = AppDomain.CurrentDomain.BaseDirectory;

string pContent = string.Empty;

OleDbConnection oledbConn = new OleDbConnection();
OleDbCommand oledbCmd = new OleDbCommand();
OleDbDataReader dataReader;
try
{
//两种连接方式皆可
//string strConnOledb = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
string strConnOledb="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=";
strConnOledb += filePath;
strConnOledb += ";Extended Properties='Text;HDR=Yes;IMEX=1;'";

oledbConn.ConnectionString = strConnOledb;
oledbConn.Open();
StringBuilder commandText = new StringBuilder("SELECT ");
commandText.AppendFormat("* From {0}", tableName);
oledbCmd.Connection = oledbConn;
oledbCmd.CommandText = commandText.ToString();
dataReader = oledbCmd.ExecuteReader();


while (dataReader.Read())
{
pContent = Convert.ToString(dataReader["content"]);
}
dataReader.Close();
}
catch (System.Exception ex)
{
oledbConn.Close();
}
finally
{
oledbConn.Close();
}

Console.WriteLine(pContent);
}


完全没有问题,没有出现你说的那种情况。给你来个截图:


我明白你的意思,你试试在Excel前面十行的字符串不超过50个字符,然后在11行后的字符串超过260个字符,试试这样读取行不行?我试过的,在前面8行前,如果字符串不超过260个字符的,后面如果有超过就读取不全了,而如果在前8行有字符串超过260个字符,后面如果有同等长度字符串,还是能读全的。所以,我判断你的长字符串是放在EXCEL的前8行了,要不你按照我说的再试试?起码你也碰到这样问题了,提前为以后准备,呵呵[/quote]
我试了 也没出现你说的那种情况啊 难道是我试得不对 还有如果你真的出现这种情况 你把你Excel里面的内容用引号包起来在试试
琴弦里的海 2014-07-22
  • 打赏
  • 举报
回复
引用 7 楼 huangcailian 的回复:

 public static void Main(string[] args)
        {
            QueryCSV();

            Console.ReadLine();
        }

        public static void QueryCSV()
        {
            //文件路径
            string tableName = "file.csv";
            string filePath = AppDomain.CurrentDomain.BaseDirectory;

            string pContent = string.Empty;

            OleDbConnection oledbConn = new OleDbConnection();
            OleDbCommand oledbCmd = new OleDbCommand();
            OleDbDataReader dataReader;
            try
            {
                //两种连接方式皆可
                //string strConnOledb = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
                string strConnOledb="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=";
                strConnOledb += filePath;
                strConnOledb += ";Extended Properties='Text;HDR=Yes;IMEX=1;'";

                oledbConn.ConnectionString = strConnOledb;
                oledbConn.Open();
                StringBuilder commandText = new StringBuilder("SELECT ");
                commandText.AppendFormat("* From {0}", tableName);
                oledbCmd.Connection = oledbConn;
                oledbCmd.CommandText = commandText.ToString();
                dataReader = oledbCmd.ExecuteReader();

                
                while (dataReader.Read())
                {
                    pContent = Convert.ToString(dataReader["content"]);
                }
                dataReader.Close();
            }
            catch (System.Exception ex)
            {
                oledbConn.Close();
            }
            finally
            {
                oledbConn.Close();
            }

            Console.WriteLine(pContent);
        }
完全没有问题,没有出现你说的那种情况。给你来个截图:
我明白你的意思,你试试在Excel前面十行的字符串不超过50个字符,然后在11行后的字符串超过260个字符,试试这样读取行不行?我试过的,在前面8行前,如果字符串不超过260个字符的,后面如果有超过就读取不全了,而如果在前8行有字符串超过260个字符,后面如果有同等长度字符串,还是能读全的。所以,我判断你的长字符串是放在EXCEL的前8行了,要不你按照我说的再试试?起码你也碰到这样问题了,提前为以后准备,呵呵
琴弦里的海 2014-07-22
  • 打赏
  • 举报
回复
引用 8 楼 geyewei 的回复:
[quote=引用 6 楼 han208 的回复:] [quote=引用 3 楼 geyewei 的回复:] 我做了实验,能全取出来。VB2008。Excel2007 新建立一个Excel,单元格A1里面敲入字符串“aaa”,单元格A2里面贴入你的例子, 执行程序以后,VB窗体内的TextBox1里面的内容可以显示到 2010年成功举办了2010年世界博览会。 代码

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim frm As New OpenFileDialog
        With frm
            .ShowDialog()

            If .FileName <> "" Then
                Dim strCon As String = ""
                If .FileName.EndsWith(".xlsx") Then
                    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & .FileName & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes"";"
                Else
                    strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & .FileName & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
                End If

                Dim strSQL As String = "SELECT * FROM [Sheet1$]"

                Using adp As New Data.OleDb.OleDbDataAdapter(strSQL, strCon), dtbRet As New DataTable
                    adp.Fill(dtbRet)
                    TextBox1.Text = dtbRet.Rows(0)(0)
                End Using
            End If
        End With
    End Sub
上面单元内容是个例子,是表面这个情况,格子字数未足够长的,我自己求证过,如果字数超260就出现不全了,麻烦你再试试数字超过300的看看?[/quote] 试过了,我偷懒,把你的例子在A2单元格里复制粘贴了5遍,通过上面的代码还是能正常读出到最后一句话的,大概读出来1000多个字吧。[/quote] 我明白你的意思,你试试在Excel前面十行的字符串不超过50个字符,然后在11行后的字符串超过260个字符,试试这样读取行不行?我试过的,在前面8行前,如果字符串不超过260个字符的,后面如果有超过就读取不全了,而如果在前8行有字符串超过260个字符,后面如果有同等长度字符串,还是能读全的。所以,我判断你的长字符串是放在前8行了
_小黑_ 2014-07-22
  • 打赏
  • 举报
回复
用 NPOI 吧 不会 出现 这样的情况 而且 还很快
geyewei 2014-07-18
  • 打赏
  • 举报
回复
引用 6 楼 han208 的回复:
[quote=引用 3 楼 geyewei 的回复:] 我做了实验,能全取出来。VB2008。Excel2007 新建立一个Excel,单元格A1里面敲入字符串“aaa”,单元格A2里面贴入你的例子, 执行程序以后,VB窗体内的TextBox1里面的内容可以显示到 2010年成功举办了2010年世界博览会。 代码

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim frm As New OpenFileDialog
        With frm
            .ShowDialog()

            If .FileName <> "" Then
                Dim strCon As String = ""
                If .FileName.EndsWith(".xlsx") Then
                    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & .FileName & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes"";"
                Else
                    strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & .FileName & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
                End If

                Dim strSQL As String = "SELECT * FROM [Sheet1$]"

                Using adp As New Data.OleDb.OleDbDataAdapter(strSQL, strCon), dtbRet As New DataTable
                    adp.Fill(dtbRet)
                    TextBox1.Text = dtbRet.Rows(0)(0)
                End Using
            End If
        End With
    End Sub
上面单元内容是个例子,是表面这个情况,格子字数未足够长的,我自己求证过,如果字数超260就出现不全了,麻烦你再试试数字超过300的看看?[/quote] 试过了,我偷懒,把你的例子在A2单元格里复制粘贴了5遍,通过上面的代码还是能正常读出到最后一句话的,大概读出来1000多个字吧。
会飞的溜溜 2014-07-18
  • 打赏
  • 举报
回复
nvarchar max=4000 l;varchar max=8000 用直接引擎操作的 应该是的字段长度的问题
琴弦里的海 2014-07-17
  • 打赏
  • 举报
回复
引用 3 楼 geyewei 的回复:
我做了实验,能全取出来。VB2008。Excel2007 新建立一个Excel,单元格A1里面敲入字符串“aaa”,单元格A2里面贴入你的例子, 执行程序以后,VB窗体内的TextBox1里面的内容可以显示到 2010年成功举办了2010年世界博览会。 代码

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim frm As New OpenFileDialog
        With frm
            .ShowDialog()

            If .FileName <> "" Then
                Dim strCon As String = ""
                If .FileName.EndsWith(".xlsx") Then
                    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & .FileName & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes"";"
                Else
                    strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & .FileName & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
                End If

                Dim strSQL As String = "SELECT * FROM [Sheet1$]"

                Using adp As New Data.OleDb.OleDbDataAdapter(strSQL, strCon), dtbRet As New DataTable
                    adp.Fill(dtbRet)
                    TextBox1.Text = dtbRet.Rows(0)(0)
                End Using
            End If
        End With
    End Sub
上面单元内容是个例子,是表面这个情况,格子字数未足够长的,我自己求证过,如果字数超260就出现不全了,麻烦你再试试数字超过300的看看?
小K的大师兄 2014-07-17
  • 打赏
  • 举报
回复

public static void Main(string[] args)
{
QueryCSV();

Console.ReadLine();
}

public static void QueryCSV()
{
//文件路径
string tableName = "file.csv";
string filePath = AppDomain.CurrentDomain.BaseDirectory;

string pContent = string.Empty;

OleDbConnection oledbConn = new OleDbConnection();
OleDbCommand oledbCmd = new OleDbCommand();
OleDbDataReader dataReader;
try
{
//两种连接方式皆可
//string strConnOledb = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
string strConnOledb="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=";
strConnOledb += filePath;
strConnOledb += ";Extended Properties='Text;HDR=Yes;IMEX=1;'";

oledbConn.ConnectionString = strConnOledb;
oledbConn.Open();
StringBuilder commandText = new StringBuilder("SELECT ");
commandText.AppendFormat("* From {0}", tableName);
oledbCmd.Connection = oledbConn;
oledbCmd.CommandText = commandText.ToString();
dataReader = oledbCmd.ExecuteReader();


while (dataReader.Read())
{
pContent = Convert.ToString(dataReader["content"]);
}
dataReader.Close();
}
catch (System.Exception ex)
{
oledbConn.Close();
}
finally
{
oledbConn.Close();
}

Console.WriteLine(pContent);
}


完全没有问题,没有出现你说的那种情况。给你来个截图:
wangnaisheng 2014-07-16
  • 打赏
  • 举报
回复
是不是你导出数据表的字段设置的长度不够,自动给截取掉了。
wind_cloud2011 2014-07-16
  • 打赏
  • 举报
回复
你读取excel时是不是读全所有内容,再看看数据库字段,如果内容多就用文本,
wangnaisheng 2014-07-16
  • 打赏
  • 举报
回复
引用 2 楼 han208 的回复:
[quote=引用 1 楼 wangnaisheng 的回复:] 是不是你导出数据表的字段设置的长度不够,自动给截取掉了。
我是在读取Excel的时候以Message输出的,同样的有丢失,而数据表字段我是设置了nvarchar(MAX)[/quote] nvarchar(MAX) 的max好像是8000,我导入过excel,基本不会丢数据的。 你试试3楼的代码吧。对比你的,看有什么问题。 其实最好还是你在你代码处设置断点调试,看看读取excel的值到底是多少。
geyewei 2014-07-16
  • 打赏
  • 举报
回复
我做了实验,能全取出来。VB2008。Excel2007 新建立一个Excel,单元格A1里面敲入字符串“aaa”,单元格A2里面贴入你的例子, 执行程序以后,VB窗体内的TextBox1里面的内容可以显示到 2010年成功举办了2010年世界博览会。 代码

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim frm As New OpenFileDialog
        With frm
            .ShowDialog()

            If .FileName <> "" Then
                Dim strCon As String = ""
                If .FileName.EndsWith(".xlsx") Then
                    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & .FileName & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes"";"
                Else
                    strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & .FileName & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
                End If

                Dim strSQL As String = "SELECT * FROM [Sheet1$]"

                Using adp As New Data.OleDb.OleDbDataAdapter(strSQL, strCon), dtbRet As New DataTable
                    adp.Fill(dtbRet)
                    TextBox1.Text = dtbRet.Rows(0)(0)
                End Using
            End If
        End With
    End Sub
加载更多回复(1)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧