C# -> Excel -> "Number Stored as Text" hiba
2008-09-23T10:25:12+02:00
2008-09-23T14:19:08+02:00
2022-07-29T23:55:31+02:00
Hix
Sziasztok!

Már egy napja túrom a netet, de még nem találtam megoldást a problémámra. Riportokat készítek, és a végeredményt Excelben szeretnék megkapni. De sajnos, azoknál az oszlopoknál, ahol számot iratok ki, mindig előjön a fent említett "Number Stored as Text" hiba. Ezidáig nem találtam megoldást a problémámra. Eddig ez a Microsoft KB cikk volt a legígéretesebb: http://support.microsoft.com/kb/316934/EN-US/, de sajnos ez sem oldotta meg a dolgot.

Elmondom, hogy pontosan mit is csinálok:
Van egy List-em, annak a tartalmát akarom kiírni egy Resource-ként tárolt Excel file adott fülébe (egy másik fül pivot táblája, meg ebből olvas). Összegyűjtöm az adatokat a List-be, kiírom a Resource-ból az Excel file-t valahova, majd feltöltöm a fület így:

string ConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + OutFile + ";Extended Properties=\"Excel 8.0;HDR=YES\""; DbProviderFactory OutFactory = DbProviderFactories.GetFactory("System.Data.OleDb"); using (DbConnection OutConn = OutFactory.CreateConnection()) { OutConn.ConnectionString = ConnStr; using (DbCommand OutDBCommand = OutConn.CreateCommand()) { OutConn.Open(); System.Text.StringBuilder SB = new System.Text.StringBuilder(); DbParameter POriginAm = OutFactory.CreateParameter(); POriginAm.ParameterName = "@POriginAm"; POriginAm.DbType = DbType.Single; DbParameter PNettAm = OutFactory.CreateParameter(); PNettAm.ParameterName = "@PNettAm"; POriginAm.DbType = DbType.Decimal; OutDBCommand.Parameters.Add(POriginAm); OutDBCommand.Parameters.Add(PNettAm); foreach (var Row in Query) { SB.Remove(0, SB.Length); SB.Append("INSERT INTO [Source$] ([Admin], [Ledger ISO], [Reference 1], [Journal ID], [Curr], [Original amount], [Nett amount], [Last used], [Ledger], [ISO], [Date], [Explanation], [Controller], [Area], [Region], [Ageing], [Age > xx days], [Unit], [Age > xx month]) VALUES ("); SB.Append(Row.Admin); . .//ez itt nem lényeg, de nagyon hosszú, úgyhogy kihagytam. . SB.Append(Row.AgeingInMonth); SB.Append("\")"); POriginAm.Value = Row.OriginalAMT; PNettAm.Value = Row.NetAMT; OutDBCommand.CommandText = SB.ToString(); try { OutDBCommand.ExecuteNonQuery(); } catch (Exception Ex) { throw new Exception(Ex.Message + "\r\nQuery string: " + SB.ToString(), Ex.InnerException); } ProgPos++; SetProgress(CalcProgress()); } } }

A Resource-ként tárolt Excel file-ban előre beállítottam a kérdéses oszlopokat Numeric-nak. A paramétereket helyét megjelölöm kérdőjellel.
Még azt is kipróbáltam, hogy a beszúrások után elvégeztem valamilyen műveletet az oszlopokkal (pl.: SET [Original amount] = [Original amount] * 10). Szépen el is végezte, de még mindig Text-ként tárolta a számokat.

A kérdés az, hogy ezt ADO.NET segítségével hogy lehet megoldani?
Mutasd a teljes hozzászólást!
Az Excel-es jet meghajtó egyedül a dbDouble-t ismeri, mint numerikus típust. Az a baj, hogy te kódod a paraméter típusát határozza meg és nem a mező típusát.

Amivel lehet esetleg próbálkozni: vigyél fel az excel táblába egy-két adatsort is, hátha úgy már tudni fogja a meghajtó, hogy milyen típusú az adott mező. A végén meg azokat a rekordokat törlöd a táblából.
Mutasd a teljes hozzászólást!

  • Az oszlop szöveg típusú érteket tud elfogadni te pedig számot akarsz a helyén tárolni. Változtasd meg az oszlop típusát.
    Mutasd a teljes hozzászólást!
  • A Resource-ként tárolt Excel file-ban előre beállítottam a kérdéses oszlopokat Numeric-nak.
    Mutasd a teljes hozzászólást!
  • Ez sajnos nem jelent semmit sem. A meghajtó nem nézi az Excel oszlopainak adattípusát, hanem az abban található adatokból próbál az oszlop adattípusára következtetni. Ha nincs adat az oszlopban, akkor az szinte biztos, hogy szövegesnek fogja venni.
    Mutasd a teljes hozzászólást!
  • Ezért próbáltam ezt:
    POriginAm.DbType = DbType.Decimal;
    Double, Currency, meg minden volt már benne.
    Szóval ez azt jelenti, hogy semmi esélyem ezt C#-ból befolyásolni? Amúgy van header a táblában, amire viszont mindenképp szükség van. Ezt jeleztem is neki a connectionstringben, hátha akkor nem veszi figyelembe.
    Abban bíztam, hogy van valami írásjel, mint például a dátum értékeknél a kettős kereszt, amivel megmagyarázhatom neki, hogy ez most szám lenne.
    Mutasd a teljes hozzászólást!
  • Az Excel-es jet meghajtó egyedül a dbDouble-t ismeri, mint numerikus típust. Az a baj, hogy te kódod a paraméter típusát határozza meg és nem a mező típusát.

    Amivel lehet esetleg próbálkozni: vigyél fel az excel táblába egy-két adatsort is, hátha úgy már tudni fogja a meghajtó, hogy milyen típusú az adott mező. A végén meg azokat a rekordokat törlöd a táblából.
    Mutasd a teljes hozzászólást!
  • Köszönöm, így sikerült.
    Megcsináltam az első két sort (+ header), és utána már jól töltötte fel az értékeket. Tettem egy ilyen kódot az Excel file-ba:
    Private Sub Workbook_Open() If Worksheets("Source").Rows.Count > 3 Then If Worksheets("Source").Cells(2, 3).Value = "DUMMYTOBEDELETED" Then Worksheets("Source").Rows(2).Delete End If If Worksheets("Source").Cells(2, 3).Value = "DUMMYTOBEDELETED" Then Worksheets("Source").Rows(2).Delete End If End If End Sub

    Mert máshogy sajnos nemigen tudtam volna törölni belőle, ugyanis:
    Although the Jet OLE DB Provider allows you to insert and update records in an Excel workbook, it does not allow DELETE operations. If you try to perform a DELETE operation on one or more records, you receive the following error message:
    Deleting data in a linked table is not supported by this ISAM.
    This limitation is inherent in the treatment of Excel workbooks as databases.


    Persze tudhattam volna, hogy nem megyek sokra a paraméterezgetéssel, hiszen, mint az általam belinkelt oldal is mondja:
    Data Types
    Unlike a traditional database, there is no direct way to specify the data types for columns in Excel tables. Instead, the OLE DB provider scans eight rows in a column to guess the data type for the field. You can change the number of rows to scan by specifying a value between one (1) and sixteen (16) for the MAXSCANROWS setting in the extended properties of your connection string.


    Még egyszer, köszönöm a segítséget!
    Mutasd a teljes hozzászólást!
abcd