2012-07-30 14 views
5

Widziałem, jak niektórzy użytkownicy SO napotykają problem przy próbie użycia wersji Cells.Count; kod VBA generuje błąd przepełnienia w niektórych przypadkach.Niepoprawna wartość podczas liczenia komórek w różnych wersjach programu Excel

Dla porównania, zobaczyć komentarze na this answer:

myślę, że to będzie działać, ale pojawia się błąd "overflow" i wskazuje mi do kodu „Jeśli Master.Cells.SpecialCells (xlCellTypeVisible) .Count> 0 Wtedy”--- wydaje się, że to nie jest filtrowany za nic w szczególności - user1556069

i this answer:

Czy to działa onyl (a Cells.Count nie działało), ponieważ ten ostatni użył liczby całkowitej, 16 bitów, wartość maksymalna 65 536, a cały arkusz kalkulacyjny zwrócił wartość większą? - fast_code


Jestem zakładając, że gdzieś za kulisami VBA próbuje zmusić morfologii do małej Integer (16-bit) lub długi Integer (32-bit). Liczba komórek arkusza kalkulacyjnego programu Excel 2007 spowoduje przepełnienie obu tych typów danych . Niestety nie mogę tego teraz wyizolować, ponieważ nie mam pod ręką kopii programu Excel 2007 i nie mogę odtworzyć błędu . - mwolfe02

Próbując zrozumieć to, starałem się odtworzyć siebie i dostał przepełnienia gdy próbuje przypisać Cells.Count jako liczba całkowita. Ma to sens, ponieważ wartość jest zbyt duża dla typu danych Integer.

Korzystając z poniższego kodu zarówno w programie Excel 2003, jak i 2010, otrzymałem wynik liczbowy podczas próby przypisania jako Long lub Variant.

Option Explicit 

Sub testInteger() 
    Dim i As Integer 
    i = Cells.Count 'Overflow 
    Debug.Print i 'Doesn't get this far... 
End Sub 

Sub testLong() 
    Dim l As Long 
    l = Cells.Count 
    Debug.Print l 'Prints 16777216 in both versions 
End Sub 

Sub testVariant() 
    Dim v As Variant 
    v = Cells.Count 
    Debug.Print v 'Prints 16777216 in both versions 
End Sub 

Jak widać w moich komentarzach, wartość Cells.Count jest 16777216 (który jest właściwy dla roku 2003), ale to jest taka sama dla obu wersji , i że nie ma sensu do mnie. Zacytować mwolfe02 z jednego z wyżej połączone odpowiedzi:

Excel 2007 arkusze mają 1,048,576 wierszy i kolumn 16384 w sumie 17,179,869,184 komórek.

Co mi mówi, że wartość wydrukowana w 2010 powinna być co najmniej (uważam, że tak naprawdę powinna być taka sama) 17,179,869,184.

Dlaczego więc ten numer nie jest drukowany poprawnie/dlaczego wartość 2003 została zwrócona w 2010 roku?

+2

16777216 to "0x1000000", a 17179869184 to "0x400000000" w postaci szesnastkowej tylko FYI. – TheZ

+0

Czy działa program Excel 2010 w trybie zgodności lub patrząc na plik zapisany w formacie 2003? –

+0

@TimWilliams Zacząłem od otwarcia nowej sesji programu Excel 2010, która domyślnie miała postać Book1, w której wkleiłem powyższy kod. Jak ustalić, czy jestem zgodny. tryb? – Gaffi

Odpowiedz

7

Podczas obliczania tak dużych liczb należy użyć właściwości .Countlarge.

Na przykład

Sub CellsCount() 
    Dim l As Double 
    l = ActiveSheet.Cells.CountLarge 
    Debug.Print l 
End Sub 

także nie używać Cells.Count lub Cells.CountLarge bez określania przedmiotu arkusza. Ma to na celu zapewnienie, że nie otrzymamy nieprawidłowego licznika/błędu w trybie zgodności. Podobnie nigdy nie używaj Rows.Count. Zawsze używaj ws.Rows.Count. Jest to najczęstszy błąd popełniany podczas próby znalezienia ostatniego wiersza w programie Excel. Na przykład

Ten

lRow = ws.Range("A" & Rows.Count).End(xlUp).Row 

i

lRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row 

nie może dać takie same wyniki zawsze.

Polecam również dalsze czytanie this.

+0

Dzięki, Sid. Doceniam twój wgląd. (Mimo to, dlaczego MSFT musiał mieć oba ".Count' * i *' .CountLarge' ...?) – Gaffi

+2

To jest jak pytanie dlaczego MS ma Excel 2003 i Excel 2007: P. '.CountLarge' został wprowadzony w programie Excel 2007 i nie był dostępny w poprzednich wersjach programu Excel. Właściwość 'Count' używa typu Long Data, więc największą możliwą do zapamiętania wartością jest 2 147 483 647. '.CountLarge' używa podwójnego typu danych, który może obsłużyć do 1,79 + E^308. –

+1

+1: W celu zapewnienia kompatybilności wstecznej możesz włączyć sprawdzanie oparte na 'val (application.version)> = 12' i użyć Cells.Countlarge, jeśli true i Cells.Count w inny sposób. Zauważ, że jeśli używasz podwójnych do zapisywania liczb całkowitych, możesz również trafić w limit z powodu 15 cyfr precyzji ~ 2^50, ale to znacznie przewyższa rozmiar siatki 2^20 * 2^14 = 2^34. –

Powiązane problemy