2015-10-12 11 views
14

Pracuję nad aplikacją, w której można wyeksportować niektóre dane do pliku Excel za pomocą OpenXML. Wszystko działa dobrze, z wyjątkiem autofiltra. Chodzi o to, aby dodać autofiltr do głównej części danych, aby użytkownik automatycznie sterował filtrowaniem i sortowaniem danych. Tak w kodzie zrobić coś takiego:Dodanie autofiltra i sortowanie powoduje awarię programu Excel

var filter = new AutoFilter() { Reference = string.Format("{0}:{1}", topLeftCellReference, bottomRightCellReference) }; 
worksheet.AppendChild(filter); 

w eksportowanym XLSX wydaje się coś takiego:

<x:autoFilter ref="A4:L33" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" /> 

A jest on dodawany do arkusza pomiędzy sheetData i mergeCells.

Mogę następnie otworzyć ten filtr w programie Excel i działa dobrze. Oczekuj, że jeśli spróbujesz posortować kolumnę, kolumna zostanie posortowana, a następnie program Excel ulegnie awarii. Zapisanie i ponowne załadowanie pliku (co zmusza program Excel do wyczyszczenia wszystkiego) nie rozwiązuje problemu. Ale jeśli najpierw zastosujesz filtr (powiedz filtrowanie kolumny do > 10, a następnie usuń ten filtr, możesz teraz sortować bez awarii.Zapisałem plik po zastosowaniu filtru i usunięciu go i teraz ten plik jest w porządku, ale patrząc na XML "naprawionego" pliku, nie widzę żadnej widocznej różnicy

Czy ktoś ma pojęcie, co może spowodować problem? Czy jest coś innego co powinienem zrobić, gdy stosuję filtr automatyczny inny niż tylko dodanie go do arkusza

Uwaga: Używamy Excel 2010 (wersja 14.0.7153.5000)

Oto przykład file (kliknij odsyłacz i będzie ona pobrać jako .zip. Zmień nazwę na .xlsx, aby otworzyć w Excelu. Włącz edycję, wybierz jedną z kolumn i spróbuj sortować).

Edytuj: więcej zabawy z tym. Jeśli ponownie zapisujesz plik w programie Excel, nadal jest on uszkodzony. Jeśli jednak najpierw zastosujesz filtr (a następnie wyczyścisz go), a następnie zapiszesz w programie Excel, otrzymasz działający plik. Patrząc bliżej na dwóch plików (wciąż łamane pliku ponownie zapisany i teraz plik roboczy), ja nie zauważy to dodatkowy bit dodawane do skoroszytu po filtr został zastosowany (i wyczyszczone):

<x:definedNames> 
    <x:definedName name="_xlnm._FilterDatabase" localSheetId="0" hidden="1">'Sheet 1'!$A$1:$E$11</x:definedName> 
    </x:definedNames> 

Nie jestem pewien, czy to może być coś, czy nie ...

+0

@mason: OpenXML pozwala na dokonanie nieprawidłowych plików EXCEL cały czas. Ponieważ reguły dla poprawnego pliku Excel są bardziej rygorystyczne (i całkowicie nieudokumentowane) niż reguły dla poprawnego pliku OpenXML (przykład, nic w standardzie nie nakazuje kolejności dzieci w "arkuszu", ale Excel jest bardzo wybredny, jeśli chodzi o pewne dzieci powinno się pojawić). Zazwyczaj program Excel narzeka (z bardzo niepomyślnym komunikatem o błędzie) przy pierwszym otwieraniu pliku. Ale ten plik otwiera się dobrze, a problem pojawia się tylko wtedy, gdy spróbujesz posortować kolumnę. –

+0

Kolejność elementów jest poprawna (zobacz moją [odpowiedź autofiltra tutaj] (http://stackoverflow.com/a/25410242/3791802) dla dokumentacji zamówienia). Jedyny problem zgłoszony przez narzędzie Productivity jest jednym z elementów 'Color' na' Font' jest niepoprawny - mam [inna odpowiedź] (http://stackoverflow.com/questions/29989234/change-sheet-tab-color -of-excel-file-using-open-xml/29991215 # 29991215) z informacją o 'Colour's, ale wątpię, że to pomoże. Przyjrzę się i zobaczę, czy mogę coś wymyślić ... – petelids

+0

@petelids: Dzięki za spojrzenie i podziękowania dla szefów, w których rzeczywiście jest określone zamówienie. Nie zdawałem sobie sprawy, że to tam jest, a to może mnie uratować. –

Odpowiedz

4

Ok, więc wydaje się, że magiczna formuła jest tu dodać DefinedNames część jak zasugerowałem w moim EDIT:

<x:definedName name="_xlnm._FilterDatabase" localSheetId="0" hidden="1">'Sheet 1'!$A$1:$E$11</x:definedName> 

Widocznie _xlmn._FilterDatabase potrzebnej do Autofiltru praca (przynajmniej do sortowania). Domyślam się, że jeśli nie ma go podczas filtrowania, zostaje utworzony, ale jeśli go nie ma podczas sortowania, wysadza Excel. .

Więc trzeba się nazwa arkusza i odwołanie do komórki, aby wypełnić go w

Patrząc poprzez otwarty standard XML, w punkcie 18.2.5 z definedName, widzę to:

Filter & zaawansowane Filtr

_xlnm. Kryteria: ta zdefiniowana nazwa odnosi się do zakresu zawierającego wartości kryteriów do zastosowania przy zastosowaniu filtru zaawansowanego do zakresu danych.

_xlnm ._FilterDatabase: może być jednym z następujących

a. ta zdefiniowana nazwa odnosi się do zakresu, do którego zastosowano zaawansowany filtr, który został zastosowany jako . Reprezentuje źródłowy zakres danych, niefiltrowany.

b. Ta zdefiniowana nazwa odnosi się do zakresu, do którego zastosowano filtr automatyczny ( ).

Wygląda więc na to, że trzeba dodać _xlnm._FilterDatabase dla każdego arkusza, który ma filtr (wydaje się, nie ma sposobu, aby mieć więcej niż jeden filtr na jednym arkuszu). Nazwa jest taka sama, _xlmn_FilterDatabase niezależnie od liczby arkuszy, które masz z filtrami, ponieważ domyślam się, że tylko kombinacja nazwy i localSheetId musi być unikalna.

Więc w końcu, mam coś takiego:

var filter = new AutoFilter() { Reference = string.Format("{0}:{1}", topLeftCellReference, bottomRightCellReference) }; 
worksheet.AppendChild(filter); 

workbookPart.Wookbook.DefinedNames.AppendChild(new DefinedName(string.Format("'{0}'!$A${1}:${2}${3}", 
    sheet.Name, 
    leftColumnLetter, 
    topRowIndex, 
    rightColumnLetter, 
    bottomRowIndex)) 
{ 
    Name = "_xlnm._FilterDatabase", 
    LocalSheetId = sheet.SheetId - 1, 
    Hidden = true 
}); 

To wydaje się jak to działa wokół błędu w programie Excel. Program Excel powinien sprawdzić, czy nazwa została zdefiniowana przed sortowaniem i utworzyć ją automatycznie w razie potrzeby (co wydaje się robić, jeśli filtrujesz, a nie sortujesz).

+0

Dziękuję bardzo! Miałem ten sam problem podczas generowania programu Excel w javascript podczas próby rozszerzenia biblioteki ExcelBuilder. To wystarczy! – nbeuchat

Powiązane problemy