web-dev-qa-db-fra.com

Obtenir l'index de colonne d'une cellule dans Excel à l'aide d'OpenXML C #

Cela fait un moment que je regarde autour de moi et n'arrive pas à trouver comment faire. J'ai une feuille Excel que je lis sous OpenXML. Maintenant, la chose normale serait de parcourir les lignes, puis les cellules pour obtenir les valeurs, ce qui est correct. Mais avec les valeurs, j'ai besoin de l'emplacement de la cellule, qui serait au format (rowindex, ColumnIndex). J'ai réussi à obtenir le rowIndex, mais je n'arrive pas à comprendre comment obtenir l'index de la colonne.

En fait, je pensais que cela allait être facile mais apparemment ce n’est pas le cas. 

11
QV1

Ceci est légèrement plus compliqué que vous ne pouvez l’imaginer car le schéma permet d’omettre les cellules vides.

Pour obtenir l'index, vous pouvez utiliser l'objet Cell avec une propriété CellReference donnant la référence au format A1, B1, etc. Vous pouvez utiliser cette référence pour extraire le numéro de colonne.

Comme vous le savez probablement, dans Excel A = 1, B = 2 etc. jusqu'à Z = 26, les cellules sont précédées du préfixe A pour donner AA = 27, AB = 28 etc. Notez que, dans le cas de AA, la première A a une valeur de 26 fois la seconde; c’est-à-dire qu’elle «vaut» 26 alors que la deuxième A vaut «vaut» 1, pour un total de 27.

Pour élaborer l’index des colonnes, vous pouvez inverser les lettres, puis prendre la valeur de la première lettre et l’ajouter à un total cumulé. Ensuite, prenez la valeur de la deuxième lettre et multipliez-la par 26, en additionnant le total au premier chiffre. Pour le troisième, multipliez-le par deux fois et ajoutez-le; pour le quatrième, multipliez-le par 26 et ainsi de suite.

Donc pour la colonne ABC vous feriez:

C = 3
B = 2 * 26 = 52
A = 1 * 26 *26 = 676
3 + 52 + 676 = 731

En C #, ce qui suit fonctionnera:

private static int? GetColumnIndex(string cellReference)
{
    if (string.IsNullOrEmpty(cellReference))
    {
        return null;
    }

    //remove digits
    string columnReference = Regex.Replace(cellReference.ToUpper(), @"[\d]", string.Empty);

    int columnNumber = -1;
    int mulitplier = 1;

    //working from the end of the letters take the ASCII code less 64 (so A = 1, B =2...etc)
    //then multiply that number by our multiplier (which starts at 1)
    //multiply our multiplier by 26 as there are 26 letters
    foreach (char c in columnReference.ToCharArray().Reverse())
    {
        columnNumber += mulitplier * ((int)c - 64);

        mulitplier = mulitplier * 26;
    }

    //the result is zero based so return columnnumber + 1 for a 1 based answer
    //this will match Excel's COLUMN function
    return columnNumber + 1;
}

Notez que la CellReference est garantie pas d'être dans le XML non plus (même si je ne l'ai jamais vu pas là). Dans le cas où la variable CellReference est nulle, la cellule est placée dans la cellule disponible la plus à gauche. La variable RowIndex n'est pas non plus obligatoire dans la spécification, elle peut donc également être omise, auquel cas la cellule est placée dans la rangée la plus élevée disponible. Plus d'informations peuvent être vues dans cette question . Le réponse de @BCdotWEB est une approche correcte dans les cas où CellReference est null.

18
petelids

Le petit est beau

int ColumnIndex(string reference)
{
  int ci=0;
  reference=reference.ToUpper();
  for (int ix = 0; ix < reference.Length && reference[ix] >= 'A';ix++ ) 
       ci = (ci * 26) + ((int)reference[ix] - 64);
  return ci;
}
7
Luc Vandenbroucke

Pour commencer à répondre, je vous invite à regarder this first.

Comme je l'ai expliqué, il existe NO un moyen simple d'extraire Row et Column. Le plus proche que vous obtenez est l'extraction de CellReference d'une cellule qui aurait la forme de A1, B2 qui est actuellement au format COLUMN_ROW.

Ce que vous pouvez faire est d'extraire Row et Column de la CellReference. Oui, vous devez implémenter une méthode dans laquelle vous devez vérifier char par charpour vérifier les nombres et les chaînes.

Disons que vous avez A11, puis lorsque vous avez besoin d'indexer une colonne, vous devez extraire A, ce qui donnerait column 1. Oui, ce n'est pas si facile, mais c'est le seul moyen sauf si vous choisissez simplement de compter les colonnes lorsque vous parcourez/parcourez les cellules.

Encore une fois, regardez ceci répondez aux questions qui font la même chose.

3
    [TestCase( 1, 0, "A1" )]
    [TestCase( 2, 25, "Z2" )]
    [TestCase( 2, 38, "AM2" )]
    [TestCase( 2, (26 * 4) + 1, "DB2" )]
    [TestCase( 2, (26 * 26 * 26 * 18) + (26 * 26 * 1) + (26 * 26 * 1) + ( 26 * 1 ) + 2, "RBAC2" )]
    public void CanGetCorrectCellReference( int row, int column, string expected )
        => GetCellReference( (uint)row, (uint)column ).Value.ShouldEqual( expected );

    public static StringValue GetCellReference( uint row, uint column ) =>
        new StringValue($"{GetColumnName("",column)}{row}");

    static string GetColumnName( string prefix, uint column ) => 
        column < 26 ? $"{prefix}{(char)( 65 + column)}" : 
        GetColumnName( GetColumnName( prefix, ( column - column % 26 ) / 26 - 1 ), column % 26 );
3
Johan Andersson
    Row row = worksheetPart.Worksheet.GetFirstChild<SheetData>().Elements<Row>().FirstOrDefault();
   var totalnumberOfColumns = 0;
    if (row != null)
        {
            var spans = row.Spans != null ? row.Spans.InnerText : "";
                if (spans != String.Empty)
                        {
                            //spans.Split(':')[1];
                            string[] columns = spans.Split(':');
                            startcolumnInuse = int.Parse(columns[0]);
                            endColumnInUse = int.Parse(columns[1]);
                            totalnumberOfColumns = int.Parse(columns[1]);
                        }
        }

ceci consiste à trouver le nombre total de colonnes présentes/utilisées enter image description here

1
tejashiwini