Question

J'ai un travail C # /. Net qui importe des données à partir d'Excel, puis les traite. Notre client dépose les fichiers et nous les traitons (c'est important car je n'ai aucun contrôle sur le fichier d'origine).

J'utilise la bibliothèque OleDb pour remplir un ensemble de données (je déteste écrire ce code. Sérieusement, existe-t-il un code qu'un développeur .Net redoute en écrivant plus que cela?). Le fichier contient des nombres tels que 30829300, 30071500, etc. Le type de données pour ces colonnes est "Texte".

Ces nombres sont convertis en notation scientifique lors de l'importation des données. Est-il possible d'empêcher que cela se produise?

-Chris

Était-ce utile?

La solution

La bibliothèque OleDb va le plus souvent gâcher vos données dans une feuille de calcul Excel. Cela tient en grande partie au fait que tout est forcé dans une disposition de colonne de type fixe, devinant le type de chaque colonne à partir des valeurs des 8 premières cellules de chaque colonne. Si elle devine mal, vous vous retrouvez avec des chaînes de chiffres converties en notation scientifique. Blech!

Pour éviter cela, mieux vaut sauter OleDb et lire la feuille directement. Vous pouvez le faire en utilisant l'interface COM d'Excel (également blech!) Ou un lecteur tiers compatible .NET Excel. SpreadsheetGear est l'une de ces bibliothèques qui fonctionne relativement bien et possède une interface très similaire à celle de l'interface COM d'Excel.

Autres conseils

Une solution à ce problème consiste à modifier votre instruction select au lieu de SELECT *, procédez comme suit:

"SELECT Format([F1], 'General Number')  From [Sheet1$]"
 -or-
"SELECT Format([F1], \"#####\")  From [Sheet1$]"

Toutefois, cela va exploser si vos cellules contiennent plus de 255 caractères avec l'erreur suivante: "Une opération OLE DB à étapes multiples a généré des erreurs. Vérifiez chaque valeur d'état OLE DB, si disponible. Aucun travail n'a été effectué. "

Heureusement, mon client ne s'est pas soucié de l'erreur dans ce scénario.

Cette page propose également de bonnes choses à essayer: http: //www.dicks- blog.com/archives/2004/06/03/external-data-mixed-data-types/

Utilisation de cette chaîne de connexion:

Provider=Microsoft.ACE.OLEDB.12.0; data source={0}; Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1\"

avec Excel 2010, j'ai remarqué ce qui suit. Si le fichier Excel est ouvert lors de l'exécution de OLEDB SELECT, vous obtenez la version actuelle des cellules et non les valeurs du fichier enregistré. De plus, les valeurs de chaîne renvoyées pour un nombre long, une valeur décimale et une date se présentent comme suit:

5.0130370071e+012
4.08
36808

Si le fichier n'est pas ouvert, les valeurs renvoyées sont:

5013037007084
£4.08
Monday, October 09, 2000

Si vous examinez le fichier .XSLX actuel à l'aide de l'outil de productivité Open XML SDK 2.0 (ou décompressez simplement le fichier et affichez le code XML dans le bloc-notes), vous verrez qu'Excel 2007 stocke les données brutes au format scientifique.

Par exemple, 0,00001 est stocké sous le nom 1.0000000000000001E-5

<x:c r="C18" s="11" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:v>1.0000000000000001E-5</x:v>
</x:c>

En regardant la cellule dans Excel, elle affiche 0.00001 dans la cellule et dans la barre de formule. Il n’est donc pas toujours vrai que le problème soit causé par OleDB.

J'ai constaté que le moyen le plus simple consiste à choisir le format Zip plutôt que le format texte pour les colonnes avec de grands "nombres".

Avez-vous essayé de transtyper la valeur du champ en (int) ou peut-être (Int64) au fur et à mesure de votre lecture?

Recherchez l'option de chaîne de connexion IMEX = 1 et le paramètre de registre TypeGuessRows sur Google. En réalité, il n’ya pas de solution simple car le lecteur déduit les types de données de colonne en consultant les premières lignes (8 par défaut). Si les lignes contiennent tous les chiffres, vous n’avez pas de chance.

Une solution de contournement que j'ai utilisée par le passé consiste à utiliser l'option de chaîne de connexion HDR = NO et à définir la valeur du paramètre de Registre TypeGuessRows sur 1, ce qui l'oblige à lire la première ligne en tant que données valides pour déterminer le type de données. plutôt qu'un en-tête. C'est un bidouillage, mais ça marche. Le code lit la première ligne (contenant l'en-tête) sous forme de texte, puis définit le type de données en conséquence.

Changer le registre est une tâche difficile (et pas toujours possible), mais je vous conseillerais de restaurer la valeur d'origine par la suite.

Si vos données d'importation ne comportent pas de ligne d'en-tête, une autre option consiste à prétraiter le fichier et à insérer un caractère 'avant chacun des chiffres de la colonne en cause. Cela entraîne le traitement des données de colonne en tant que texte.

Donc dans l’ensemble, il y a un tas de bidouilles pour résoudre ce problème, mais rien de vraiment infaillible.

J'ai eu le même problème, mais j'ai pu contourner le problème sans recourir à l'interface COM Excel ou à un logiciel tiers. Cela implique un peu de temps de traitement mais semble fonctionner pour moi.

  1. Commencez par lire les données pour obtenir les noms de colonne
  2. Créez ensuite un nouveau DataSet avec chacune de ces colonnes, en définissant chacun de leurs DataTypes sur string.
  3. Relisez les données dans cette nouvelle ensemble de données. Voila - le scientifique la notation est maintenant partie et tout est lu comme une chaîne.

Voici un code qui illustre cela, et en prime, il est même StyleCopped!

public void ImportSpreadsheet(string path)
{
    string extendedProperties = "Excel 12.0;HDR=YES;IMEX=1";
    string connectionString = string.Format(
        CultureInfo.CurrentCulture,
        "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"{1}\"",
        path,
        extendedProperties);

    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        using (OleDbCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT * FROM [Worksheet1$]";
            connection.Open();

            using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
            using (DataSet columnDataSet = new DataSet())
            using (DataSet dataSet = new DataSet())
            {
                columnDataSet.Locale = CultureInfo.CurrentCulture;
                adapter.Fill(columnDataSet);

                if (columnDataSet.Tables.Count == 1)
                {
                    var worksheet = columnDataSet.Tables[0];

                    // Now that we have a valid worksheet read in, with column names, we can create a
                    // new DataSet with a table that has preset columns that are all of type string.
                    // This fixes a problem where the OLEDB provider is trying to guess the data types
                    // of the cells and strange data appears, such as scientific notation on some cells.
                    dataSet.Tables.Add("WorksheetData");
                    DataTable tempTable = dataSet.Tables[0];

                    foreach (DataColumn column in worksheet.Columns)
                    {
                        tempTable.Columns.Add(column.ColumnName, typeof(string));
                    }

                    adapter.Fill(dataSet, "WorksheetData");

                    if (dataSet.Tables.Count == 1)
                    {
                        worksheet = dataSet.Tables[0];

                        foreach (var row in worksheet.Rows)
                        {
                            // TODO: Consume some data.
                        }
                    }
                }
            }
        }
    }
}

J'ai googlé autour de cet état .. Voici mes étapes de solulition

  • Pour le modèle de fichier Excel

Coloumn Excel au format 1 en tant que texte 2- écrivez une macro pour désactiver les avertissements d'erreur pour Number - > conversion de texte

  Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.ErrorCheckingOptions.BackgroundChecking = Ture
End Sub
Private Sub Workbook_Open()
Application.ErrorCheckingOptions.BackgroundChecking = False
End Sub
  • sur codebehind

3- pendant la lecture des données à importer essayez d’analyser les données entrantes en Int64 ou Int32 ....

Je suis intéressé de savoir si quelqu'un a une réponse à cette question. Je suis allé de haut en bas sur les interwebs et j'ai essayé toutes les combinaisons d'IMEX et de HDR. IMEX = 1 est le seul avec lequel j'ai réussi à extraire les valeurs de date, de devise et de nombre général. Mais les grands nombres apparaissent toujours comme scientifiques. Je n'ai besoin que de lire des fichiers et de changer de feuille de calcul, de registre, de tierce partie n'est pas une option.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top