ArcGis dbf讀寫——掛接Excel到屬性表 C#


ArcMap提供了掛接Excel表格信息到屬性表的功能,但是當數據量較大到以萬計甚至十萬計的時候這個功能就歇菜了,當然,你可以考慮分段掛接。這個掛接功能只是做了一個表關聯,屬性記錄每個字段的信息需要通過“字段計算器”計算過來。

Excel數據寫入ArcGis屬性表功能開發實例中,博主見到太多使用UpdateCursor的方式,界面卡翔,效率感人。

ArcGis Shapefile的屬性表信息存放在一個dbf格式(dbaseIV,dbf4,dbase4,下稱dbf4)的文件中,那么,有沒有一種方式可以通過直接對它的讀寫實現快速掛接?通過數據庫連接的方式可以實現,但是對客戶機的環境配置有要求,起碼得有OLEDB、ODBC驅動……,這樣整不爽。那么,有沒有一種方式可以借由第三庫或者某種方式去直接解析它呢?博主去分析了這個可能,DBF文件的結構並不復雜,找個比較成熟的輪子來研究解析最好不過,去年,博主在GitHub發現了它——“FastDBF”,地址:https://github.com/SocialExplorer/FastDBF。該庫作者是老外,所以不出意外的對於中文環境下dbf文件的讀寫不友好,有點兒小bug,相關說明可以查找本人博客。

優點:插件方式開發下不操作ArcObject對象,並且可以使用多線程+委托的方式使掛接在子線程進行,進度傳回主線程更新UI,掛接速度快且不影響ArcMap的瀏覽使用。

  • dbf4文件格式與解析

本篇不講,可以自行百度或參考:

https://www.clicketyclick.dk/databases/xbase/format/dbf.html

需要提醒的是網上的格式解析說明文章都將dbf4編碼規則默認為ANSI(中文操作系統下是gbk,codepage=936,在非英文操作系統下,這些文章寫為ASCII並不嚴謹)去解析,而實際上ArcGis10.2之后版本生成的dbf文件默認使用了utf-8(codepage65001)編碼。這就牽涉到了“FastDBF”在中文環境下的bug。

  • FastDBF讀寫dbf4文件

打開dbf文件,注意選擇字符編碼規則

var odbf = new DbfFile(Encoding.GetEncoding(rdoGBK.Checked ? 936 : 65001));
odbf.Open(dbfPath, FileMode.Open);

讀取記錄數、字段數、長度

var header=odbf.Header;
int dbfRecordCount=Convert.ToInt32( header.RecordCount);
//header.ColumnCount字段數
for (int i = 0; i < header.ColumnCount; i++)
{
    this.dataGridView2.Rows.Add();
//字段名
    this.dataGridView2[0, i].Value = header[i].Name;
//字段類型
    this.dataGridView2[2, i].Value = header[i].ColumnType.ToString();
//字段長度與小數位
    if (header[i].DecimalCount!=0)
    {
        this.dataGridView2[3, i].Value = header[i].Length.ToString() + "," + header[i].DecimalCount;
    }
    else
        this.dataGridView2[3, i].Value = header[i].Length.ToString();
}

從DataTable中匹配記錄掛接,Excel裝入DataTable可以使用epplus,不講。

var odbf = new DbfFile(Encoding.GetEncoding(prms.encode));
DbfRecord orec;
try
{
    odbf.Open(prms.dbfPath, FileMode.Open);
    orec = odbf.Read(0);
    int i = 1;
    while (orec != null)
    {
        DataRow[] dataRows = dt.Select(linkFieldNameExcel + "=" + "'" + orec[prms.linkFieldIndexShp].ToString() + "'");
        if (dataRows.Count() > 0)
        {
            DataRow dr = dataRows.First();
            foreach (var item in prms.updateFieldPrms)
            {   string content=dr[item.fieldNamesExcel].ToString();
                int byteCount= Encoding.GetEncoding(prms.encode).GetByteCount(content);
                if (byteCount<=item.fieldLength)
                {
                    orec[item.fieldNameDbf] = content;
                }
            }
            odbf.Update(orec);
        }
        orec = odbf.ReadNext();
        ProgressChanged(this, i);
        i++;
    }
}
catch (Exception)
{
    throw new Exception("dbf掛接過程出錯!");
}
finally
{
    dt.Dispose();
    orec = null;
    odbf.Close();
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM