Подытоги Excel 2010, VBA и ListObjects не обновляются при изменении таблицы
Итак, имея эту структуру (начиная с A1-Show snippet > run):
table {
border-color: #BBB;
border-width: 0px 0px 1px 1px;
border-style: dotted;
}
body {
font: 12px Arial, Tahoma, Helvetica, FreeSans, sans-serif;
color: #333;
}
td {
border-color: #BBB;
border-width: 1px 1px 0px 0px;
border-style: dotted;
padding: 3px;
}
<table>
<tbody>
<tr>
<th></th>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
</tr>
<tr>
<td>1</td>
<td>Title 1</td>
<td>Title 2</td>
<td>Title 3</td>
<td>Title 4</td>
</tr>
<tr>
<td>2</td>
<td>GH</td>
<td>1</td>
<td>434</td>
<td>4</td>
</tr>
<tr>
<td>3</td>
<td>TH</td>
<td>3</td>
<td>435</td>
<td>5</td>
</tr>
<tr>
<td>4</td>
<td>TH</td>
<td>4</td>
<td>4</td>
<td>6</td>
</tr>
<tr>
<td>5</td>
<td>LH</td>
<td>2</td>
<td>0</td>
<td>3</td>
</tr>
<tr>
<td>6</td>
<td>EH</td>
<td>2</td>
<td>5</td>
<td>36</td>
</tr>
</tbody>
</table>
Я написал код для преобразования этого диапазона (A1: D6) в ListObject, добавил 4 новых столбца и промежуточные итоги:
Function test()
Dim objLO As ListObject
Set objLO = ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A:$D"), , xlYes)
objLO.Name = "Recap"
objLO.TableStyle = "TableStyleMedium2"
objLO.ListColumns.Add (objLO.ListColumns.Count + 1)
objLO.HeaderRowRange(objLO.ListColumns.Count) = "Tot1"
objLO.ListColumns.Add (objLO.ListColumns.Count + 1)
objLO.HeaderRowRange(objLO.ListColumns.Count) = "Tot2"
objLO.ListColumns.Add (objLO.ListColumns.Count + 1)
objLO.HeaderRowRange(objLO.ListColumns.Count) = "Tot3"
objLO.ListColumns.Add (objLO.ListColumns.Count + 1)
objLO.HeaderRowRange(objLO.ListColumns.Count) = "Tot4"
objLO.ShowTotals = True
objLO.ListColumns("Tot1").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("Tot2").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("Tot3").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("Tot4").TotalsCalculation = xlTotalsCalculationSum
End Function
теперь, если вы идете на любую ячейку новых столбцов и пишете некоторые цифры, странно, что общее (подытог) не обновляется; но если вы сохраните файл и снова откроете его, он будет работать, и итоги будут обновляться. Кто я? не хватает?
Я уже пробовал перемещать ShowTotals после TotalCalculation, но поведение остается прежним.
если мы теперь перестроим лист с нуля и добавим этот фрагмент кода для промежуточных итогов для столбцов b, c и d после применения стиля в предыдущем коде:
objLO.ListColumns("b").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("c").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("d").TotalsCalculation = xlTotalsCalculationSum
Я заметил, что промежуточные итоги для b, c и d работают, но не для Tot1, Tot2 и т. д.
кажется, что единственным обходным путем является создание необработанной таблицы до добавление ListObject со ссылками для его создания. Кто-нибудь знает лучшее решение?
спасибо заранее :)
2 ответов
в таблицах Excel есть выдающаяся ошибка, и есть некоторые тонкости, которые необходимо устранить, чтобы получить требуемый результат.
грубой исправить, используя явную хитрость расчета работает, но, хотя этот подход обновит итоги на основе текущих значений в строках данных, они должны применяться каждый раз, когда в таблице данных изменяются значения.
есть 2 способа заставить Excel вычислить итоги:
-
вы можете переключить состояние расчета родительского листа:
objLO.Parent.EnableCalculation = False objLO.Parent.EnableCalculation = True
-
или, вы можете заменить
=
в итоговых формулах:objLO.TotalsRowRange.Replace "=", "="
но ни один из вышеперечисленных подходов не дает вам прочного решения, которое держит итоги в актуальном состоянии автоматически.
лучшее решение...
ключ к решению кроется в том, что подытоги are динамически вычисляется для столбцов, которые существовал когда ListObject был преобразован из диапазона в ListObject.
вы можете использовать эти знания и убедиться, что вместо добавления столбцов в конец/справа от ListObject вы вставляете их перед существующим столбцом. Но поскольку вы в конечном итоге хотите, чтобы новые столбцы были правильными, этот подход потребует использования фиктивного столбца в исходном диапазоне, а затем всех новых столбцов вставляются до фиктивный столбец и, наконец, фиктивный столбец можно удалить.
посмотреть этот измененный код, с комментариями:
Function test()
Dim objLO As ListObject
'Expand the selection to grab an additional Dummy column
Set objLO = ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A:$E"), , xlYes)
objLO.Name = "Recap"
objLO.TableStyle = "TableStyleMedium2"
'Insert all of the new columns BEFORE the Dummy column
objLO.ListColumns.Add (objLO.ListColumns.Count)
objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot1"
objLO.ListColumns.Add (objLO.ListColumns.Count)
objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot2"
objLO.ListColumns.Add (objLO.ListColumns.Count)
objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot3"
objLO.ListColumns.Add (objLO.ListColumns.Count)
objLO.HeaderRowRange(objLO.ListColumns.Count - 1) = "Tot4"
'Must show totals BEFORE applying totals, otherwise the last column defaults to Count (even if we override it)
objLO.ShowTotals = True
objLO.ListColumns("Tot1").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("Tot2").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("Tot3").TotalsCalculation = xlTotalsCalculationSum
objLO.ListColumns("Tot4").TotalsCalculation = xlTotalsCalculationSum
'Remove the extra dummy column
objLO.ListColumns(objLO.ListColumns.Count).Delete
'Now toggle the ShowTotals to force the ListObject to recognise the new column totals
objLO.ShowTotals = False
objLO.ShowTotals = True
End Function
вы ничего не упускаете. Эта проблема кажется ошибкой, которую Microsoft еще не исправила.
единственное, что вы можете попробовать сейчас, это сохранить/закрыть/открыть книгу по коду.