2012-11-01 17 views
22

Hücrelerden birinde xlsx dosyasında "4/5/2011" biçiminde (ay/gün/yıl) bir tarihim var. Dosyayı ayrıştırmaya ve bu verileri bazı sınıflara yüklemeye çalışıyorum.Açık xml sdk'yi kullanarak xlsx'ten bir tarih okuma

Şimdiye kadar hücre şöyle ayrıştırmak parçası:

string cellValue = cell.InnerText; 
if (cell.DataType != null) 
{ 
    switch (cell.DataType.Value) 
    { 
     case CellValues.SharedString: 
      // get string from shared string table 
      cellValue = this.GetStringFromSharedStringTable(int.Parse(cellValue)); 
      break; 
    } 
} 

O tarih bir cell.DataType olacağını umuyordu. Gerçekte "4/5/2011" tarihiyle hücreyi ayrıştırırken, cell.DataType değeri boştur ve hücrenin değeri "40638" dir ve paylaşılan dize tablosu için bir dizin değildir. (Bunu daha önce denedim ve bir istisna ile bitti.)

Herhangi bir fikrin var mı? Teşekkür

ben aynı sorunu vardı

cevap

26

Açık XML depo tarihlerini 1 Ocak 1900 gün sayısı olarak. Eh, yanlış 29 Şubat 1900 geçerli bir gün olarak atlama. Doğru değeri hesaplamanıza yardımcı olacak algoritmaları öğrenebilmeniz gerekir. Bazı geliştiricilerin yardımcı olarak DateTime.FromOADate() kullandığını düşünüyorum.

Ayrıca, Cell sınıfı, DataType özelliğine varsayılan olarak Numara olarak sahiptir. Yani, eğer boşsa, bu bizim durumumuzdaki tarihleri ​​içeren bir sayıdır.

Sadece paylaşılan dizeler tablosuna, depolanan tarih çağlardan önce gelir (bu durumda 1 Ocak 1900). Ve sonra bu durumda, Hücre sınıfının CellValue dizini paylaşılan dize tablosuna tutar.

+1

Nice, FromOADate ile ayrıştırma gerçekten işe yarıyor! – Santhos

+0

@Santhos, FromOADate'in yanı sıra herhangi bir ayar yapmak zorunda mısınız? @VincentTan, yalnızca bir "yardımcı yöntem" olarak bahseder. –

+2

Bu cevaplar: http://www.dotnetperls.com/fromoadate –

1

- EPPlus için o LGPL lisansa sahip olduğunu http://epplus.codeplex.com/

Not geçti. Bu nedenle, GPL sorunundan emin olmak için kod tabanınıza ihtiyacınız varsa, kütüphaneyi olduğu gibi kullanın ve orijinal kod taban lisansınız güvenlidir.

+0

xml sdk dosyasını açmayı tercih ederim, ancak bir çözüm bulamazsam bunu deneyeceğim. Teşekkürler – Santhos

+0

openxml sdk'de bir çözüm var, ancak birkaç ifadeyle devam etmek için çok kıvrık bir yol var. İşte bir işaretçi - stilleri documentpart size numberformat söyler. İçinde yineleyin, eşleşen eleman – CKmum

+0

anlamıyorum. Bu sayı biçiminin "number: #. ###" veya "date: m/d/y" gibi bir şey olmasını beklerdim. Hücreden aldığım numara bir şey ifade etmeli. Bunun ne anlama geldiğini biliyor musun? – Santhos

8

Eğer değer benim 2 peni ekleme DateTime.FromOADate (41690)

0

kullanabilirsiniz. Şablon yapıyorum, bu yüzden belirli bir hücrenin bir DateTime olması gerektiğini biliyorum. Bu nedenle, "42540.041666666664" gibi bir OADAT numarası olacak olan hücre değerini içeren bir excelDateTime dizesi parametresiyle bu yönteme son veriyorum.

public static bool TryParseExcelDateTime(string excelDateTimeAsString, out DateTime dateTime) 
{ 
    double oaDateAsDouble; 
    if (!double.TryParse(excelDateTimeAsString, out oaDateAsDouble)) //this line is Culture dependent! 
     return false; 
    //[...] 
    dateTime = DateTime.FromOADate(oaDateAsDouble); 

Benim sorunum son kullanıcı Almanya'da olmasıdır ve bu web sitesi olduğu için, biz Thread.CurrentThread.CurrentCulture ve Thread.CurrentThread.CurrentUICulture için "DE-de" kurdum. Ve double.TryParse'u aradığınızda, sayıyı ayrıştırmak için kültürü kullanır. Yani bu satır: double.TryParse("42540.041666666664", out oaDate) gerçekten çalışır, ancak Almanya'da olduğu gibi 42540041666666664 döndürür, nokta bir grup ayırıcısıdır. DateTime.FromOADate daha sonra başarısız olur, çünkü sayı aralık dışıdır (minOaDate = -657435.0, maxOaDate = +2958465.99999999).

Bu beni düşünmesine neden:? Bakılmaksızın bir kullanıcının makinesinde yerel ayarının

  1. , açık XML belge (ABD varsayılan bir yerel ayarda biçimlendirilmiş sayılar içeren değişmeyen her durumda, ondalık olarak nokta ile? ayırıcı). Ben aradım ama bunun için spec bulunamadı.
  2. double.TryParse, olası bir OADA dizesi üzerinde double.TryParse(excelDateTimeAsString, NumberStyles.Any, CultureInfo.InvariantCulture, out oaDateAsDouble)) ile yapmalıyız. Ben CultureInfo.InvariantCulture kullanıyorum, ama kesin olarak bilmediğim 1 noktası olmalı.
+0

Aynı problemi yaşadım. Bunu şu şekilde çözdüm: 'Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; –

0

Her hücre 2 özellikleri (CellReference) r ve s (StyleIndex) sayılar için

StyleIndex 2'dir ve tarih için o Odate olduğu 3

tarihi ve dize biçimine dönüştürebilirsiniz

value = DateTime.FromOADate (double.Parse (value)) ToShortDateString();

İlgili konular