Il presente articolo è stato tradotto automaticamente.
SharePoint e Open XML
Generazione di documenti da SharePoint con controlli contenuto Open XML
Eric White
È spesso il caso che un responsabile del reparto deve inviare regolarmente un rapporto di stato formattato in modo appropriato il direttore generale o che un responsabile del team deve inviare un rapporto di stato settimanale un numero di parti interessate. Per collaborare con altri utenti nelle proprie organizzazioni, è possibile mantenere informazioni sullo stato negli elenchi di SharePoint sia la gestione e il responsabile del team. La domanda per gli sviluppatori è come includere le informazioni negli elenchi in un documento, ad esempio un rapporto di stato.
XML aperto, il formato di file predefinito per Office 2007, è uno standard ISO (documentato in exacting dettaglio in IS29500). In termini semplici, Open XML file sono zip contiene XML ed è molto facile da generare o modificare i documenti Open XML a livello di programmazione. Tutto ciò che serve è una libreria per aprire un file zip e un'API XML. Utilizzo delle funzionalità programmabilità di Open XML e di SharePoint, è possibile organizzare un sistema di generazione di documenti piccole che sfrutta i controlli contenuto Open XML e inserisce persone come il gestore e il responsabile del team responsabile del report. In questo articolo, presenterò verrà alcuni Guida e il codice di esempio per la creazione di un sistema di generazione di documenti che utilizza gli elenchi di SharePoint per popolare le tabelle di un documento di elaborazione testi di Open XML.
Cenni preliminari sull'esempio
L'esempio in questo articolo è una versione piccola del Web Part di SharePoint che genera un documento di elaborazione testi di Open XML da dati che si trova in elenchi SharePoint. Ho creato due SharePoint elenchi personalizzati, nell' di figura 1, che contengono i dati che si desidera inserire le tabelle.
Nella figura 1 SharePoint personalizzato due elenchi
Ho anche creato un documento di elaborazione testi Open XML modello contenente controlli contenuto, definizione elenchi e le colonne di origine dei dati per il documento generato. I controlli vengono visualizzati in di figura 2.
nella figura 2 il modello Apri XML documento contenente controlli contenuto
Infine, è stata creata una Web Part che recupera l'elenco di documenti modello da una raccolta documenti specifica e presenta l'elenco per gli utenti. Un utente seleziona un elemento nell'elenco e quindi il pulsante Genera Report. La Web Part viene creato un documento di elaborazione testi Open XML, colloca nella raccolta documenti report e reindirizzare l'utente che la libreria in modo che utente possibile aprire il report. La Web Part è visualizzata in di figura 3, e il documento che viene generato viene visualizzato in di figura 4.
Nella figura 3 SharePoint Web Part che consente agli utenti di selezionare un modello di documento
Apri controlli contenuti XML
Prima di descrivere la soluzione di SharePoint, si parlerà le nozioni di base di controlli contenuto Open XML. I controlli di contenuto XML aperti forniscono una funzionalità che consente di delineare il contenuto e associare i metadati che il contenuto nei documenti di elaborazione testi. Per utilizzare i controlli contenuto è necessario attivare la scheda sviluppo in Microsoft Office Word 2007. (Scegliere Opzioni di Word dal menu di Office;quindi, nella finestra di dialogo Opzioni di Word, selezionare Mostra scheda sviluppo barra multifunzione.)
Per inserire un controllo contenuto, è necessario selezionare del testo e quindi fare clic sul pulsante nell'area controlli della scheda sviluppatore che crea un controllo contenuto testo normale, illustrato nella di figura 5.
Nella figura 4 un documento di elaborazione testi Open XML contenente il report generato
Nella figura 5 utilizzare questo pulsante per creare un controllo contenuto di testo normale
È possibile impostare le proprietà assegnare un titolo e assegnare un tag di un controllo contenuto. Fare clic nel controllo contenuto e quindi scegliere il pulsante Proprietà nell'area controlli nella scheda sviluppo. Verrà visualizzata una finestra di dialogo che è possibile utilizzare per impostare il titolo e il tag.
Controlli contenuto utilizzare l'elemento di w:sdt nel codice di Open XML, come illustrato nella di figura 6. Il contenuto del controllo contenuto viene definito nell'elemento w:sdtContent. Nella figura, è inoltre possibile visualizzare il titolo del controllo contenuto nell'elemento w:alias e tag del controllo contenuto nell'elemento w:tag.
Programmazione per Open XML mediante .NET Framework
È possibile eseguire diversi approcci alla programmazione per Open XML utilizzando Microsoft .NET Framework:
- Utilizzare le classi System.IO.Packaging
- Utilizzare il SDK per Open XML con il codice XML programmazione tecnologie disponibili in. NET, tra cui XmlDocument, XmlParser o LINQ to XML. Mio preferito è LINQ to XML.
- Utilizzare il modello oggetto fortemente tipizzato di Open XML SDK versione 2.0. È possibile trovare un numero di articoli che introducono come programmare con questo modello di oggetto.
In questo caso, sto per utilizzare il SDK per Open XML (entrambi versione 1.0 o 2.0) con LINQ to XML. È possibile scaricare il SDK per Open XML di go.microsoft.com/fwlink/?LinkId=127912.
È utile incapsulare alcune funzionalità di Open XML intorno ai controlli contenuti in una classe ContentControlManager. Quando si avvicina il problema in questo modo, è possibile sviluppare le funzionalità di Open XML di una semplice applicazione console. Dopo aver codificato e il debug la funzionalità Open XML, è possibile quindi incorporare, nella funzionalità di SharePoint con un minimo sforzo. È piuttosto lunga soggetti al sovraccarico di distribuire la funzionalità di SharePoint durante il debug di codice XML aperto.
Questo esempio di generazione di documenti di SharePoint, che si desidera scrivere del codice che recupera un modello di documento da una raccolta documenti specifica, query, che il documento per il contenuto i controlli contiene e utilizza i metadati archiviati nel contenuto di ogni controllo per popolare il documento con dati dall'elenco SharePoint appropriato.
Scaricare l'esempio, esaminare il documento Open XML di modello verrà visualizzato che contenga un controllo contenuto che circonda ogni tabella e che i controlli contenuto vengono inseriti in ogni cella nella riga inferiore di ogni tabella. Il tag per ogni controllo contenuto nelle celle della tabella specifica il nome di una colonna negli elenchi di SharePoint. Per comodità, È stato inoltre impostare il titolo di ogni controllo contenuto sullo stesso valore come il tag. I controlli contenuto consente di visualizzare il titolo quando il punto di inserimento è all'interno del controllo.
Quando si scrive il codice per una funzionalità di SharePoint che genera un documento Open XML, il codice deve prima una query il documento di questi controlli contenuti. La query restituisce una struttura ad albero XML che descrive la struttura dei controlli contenuto, insieme con il tag per ogni. Se si esegue questo codice nel documento di esempio, produce il seguente codice XML:
<ContentControls>
<Table Name="Team Members">
<Field Name="TeamMemberName" />
<Field Name="Role" />
</Table>
<Table Name="Item List">
<Field Name="ItemName" />
<Field Name="Description" />
<Field Name="EstimatedHours" />
<Field Name="AssignedTo" />
</Table>
</ContentControls>
In questo documento XML viene indicato che SharePoint elenca il codice deve query. Per ogni elemento nell'elenco, è necessario recuperare i valori delle colonne specificate. Il codice per il documento di elaborazione testi Open XML, visualizzato nella di figura 7, una query viene scritto come un LINQ to XML query che utilizza la costruzione funzionale per formare il XML restituito.
Per utilizzare la costruzione funzionale, il codice crea un'istanza un oggetto XElement utilizzando il costruttore, passando un LINQ to XML query come un argomento del costruttore. La query LINQ to XML utilizza di metodi axis per recuperare gli elementi appropriati nel corpo del documento e utilizza il metodo di estensione Enumerable.Select per formare nuove XML dai risultati della query. Costruzione funzionale richiede un po' di Studio per comprendere, ma come può vedere, una volta è disporre la testina intorno a esso, è possibile eseguire un lotto terribili con un po' di codice.
Nella figura 6 Apri tag XML per un controllo contenuto
<w:p>
<w:r>
<w:t xml:space="preserve">Not in content control. </w:t>
</w:r>
<w:sdt>
<w:sdtPr>
<w:alias w:val="Test"/>
<w:tag w:val="Test"/>
<w:id w:val="5118254"/>
<w:placeholder>
<w:docPart w:val="DefaultPlaceholder_22675703"/>
</w:placeholder>
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:t>This is text in content control.</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
<w:r>
<w:t xml:space="preserve"> Not in content control.</w:t>
</w:r>
</w:p>
Preatomization di XName e oggetti di XNamespace
Nel codice in di figura 7 viene utilizzato un approccio chiamato "preatomization"del LINQ to XML nomi. Questo è solo un modo decorativo che informa che è scrivere una classe statica (vedere di figura 8) che contiene i campi statici vengono inizializzati ai nomi completi degli elementi e attributi che si utilizza.
Nella figura 7 recupero della struttura di controlli di contenuto nel documento modello
public static XElement GetContentControls(
WordprocessingDocument document)
{
XElement contentControls = new XElement("ContentControls",
document
.MainDocumentPart
.GetXDocument()
.Root
.Element(W.body)
.Elements(W.sdt)
.Select(tableContentControl =>
new XElement("Table",
new XAttribute("Name", (string)tableContentControl
.Element(W.sdtPr).Element(W.tag).Attribute(
W.val)),
tableContentControl
.Descendants(W.sdt)
.Select(fieldContentControl =>
new XElement("Field",
new XAttribute("Name",
(string)fieldContentControl
.Element(W.sdtPr)
.Element(W.tag)
.Attribute(W.val)
)
)
)
)
)
);
return contentControls;
}
È una buona ragione per inizializzare gli oggetti XName e XNamespace in questo modo. LINQ to XML estrae i nomi XML e spazi dei nomi in due classi: System.Xml.Linq.XName e System.Xml.Linq.XNamespace, rispettivamente. La semantica di queste classi include la nozione che se due XNames hanno lo stesso nome completo (spazio dei nomi + nome locale), sarà rappresentate dall'oggetto stesso. In questo modo rapido confronto tra gli oggetti XName. Invece di utilizzare un confronto tra stringhe per selezionare oggetti XElement di un determinato nome, il codice deve solo confrontare oggetti. Quando si inizializza un oggetto XName, LINQ to XML ricerca innanzitutto in una cache per determinare se oggetto XName con lo stesso spazio dei nomi e lo stesso nome esiste già. Un caso, l'oggetto viene inizializzato all'oggetto XName esistente dalla cache. Se non esiste, LINQ to XML consente di inizializzare una nuova e lo aggiunge alla cache. Come può immaginare, se questo processo viene ripetuto più volte, può causare problemi di prestazioni. Inizializzando gli oggetti in una classe statica, il lavoro viene eseguito una sola volta. Inoltre, utilizzando questa tecnica è necessario ridurre la possibilità che il nome di un elemento o attributo è errato nel corpo del codice. Un altro vantaggio è che utilizzando questa tecnica, si ottiene supporto di IntelliSense, che consente di scrivere programmi Open XML utilizzo più semplice di LINQ to XML.
Nella figura 8 A classe statica contenente campi statici da Preatomize XName e oggetti di XNamespace
public static class W
{
public static XNamespace w =
"https://schemas.openxmlformats.org/wordprocessingml/2006/main";
public static XName body = w + "body";
public static XName sdt = w + "sdt";
public static XName sdtPr = w + "sdtPr";
public static XName tag = w + "tag";
public static XName val = w + "val";
public static XName sdtContent = w + "sdtContent";
public static XName tbl = w + "tbl";
public static XName tr = w + "tr";
public static XName tc = w + "tc";
public static XName p = w + "p";
public static XName r = w + "r";
public static XName t = w + "t";
public static XName rPr = w + "rPr";
public static XName highlight = w + "highlight";
public static XName pPr = w + "pPr";
public static XName color = w + "color";
public static XName sz = w + "sz";
public static XName szCs = w + "szCs";
}
I metodi di estensione PutXDocument e GetXDocument
Viene presentato in questo articolo viene inoltre utilizzata un altro piccolo trucco per semplificare la programmazione e migliorare le prestazioni. il SDK per Open XML è possibile inserire annotazioni su parti del documento. Ciò significa che qualsiasi oggetto di .NET Framework associato a un oggetto OpenXmlPart e recuperarlo successivamente specificando il tipo dell'oggetto che è collegato.
È possibile definire l'estensione utilizzare due metodi, GetXDocument e PutXDocument, le annotazioni per ridurre al minimo la deserializzazione del XML dalla parte Open XML. Quando si chiama GetXDocument, ricerca innanzitutto per verificare se un'annotazione di tipo che XDocument esista nel OpenXmlPart. Se esiste l'annotazione, GetXDocument restituisce. Se l'annotazione non esiste, il metodo compila un'istanza XDocument dalla parte, Annota la parte e quindi restituisce il nuovo XDocument.
Il metodo di estensione PutXDocument controlla inoltre se esiste un'annotazione di tipo XDocument. Se esiste questa annotazione, PutXDocument scrive il XDocument (probabilmente modificato dopo il codice chiama GetXDocument) sul OpenXMLPart. I metodi di estensione GetXDocument e PutXDocument vengono visualizzati in di figura 9. È possibile visualizzare l'utilizzo del metodo estensione GetXDocument nel metodo GetContentControls elencato in precedenza in di figura 7.
Nella figura 9 metodi di estensione consente di riduzione di deserializzazione di XML annotazioni SDK per Open XML
public static class AssembleDocumentLocalExtensions
{
public static XDocument GetXDocument(this OpenXmlPart part)
{
XDocument xdoc = part.Annotation<XDocument>();
if (xdoc != null)
return xdoc;
using (Stream str = part.GetStream())
using (StreamReader streamReader = new StreamReader(str))
using (XmlReader xr = XmlReader.Create(streamReader))
xdoc = XDocument.Load(xr);
part.AddAnnotation(xdoc);
return xdoc;
}
public static void PutXDocument(this OpenXmlPart part)
{
XDocument xdoc = part.GetXDocument();
if (xdoc != null)
{
// Serialize the XDocument object back to the package.
using (XmlWriter xw =
XmlWriter.Create(part.GetStream
(FileMode.Create, FileAccess.Write)))
{
xdoc.Save(xw);
}
}
}
}
Sostituire i controlli contenuti con dati
Ora che si dispone di un metodo che restituisce la struttura dei controlli contenuto delle tabelle e celle, è necessario un metodo (SetContentControls) che crea un documento XML aperto con specifici (recuperati dagli elenchi SharePoint) inseriti dati nelle tabelle. È possibile definire questo metodo per richiedere una struttura XML come argomento. La struttura ad albero XML viene visualizzata in di figura 10, e di figura 11 viene illustrato il documento che SetContentControls crea quando viene passata la struttura ad albero XML.
Nella figura 10 una struttura XML che contiene dati da inserire nel documento tabelle Word-Processing
<ContentControls>
<Table Name="Team Members">
<Field Name="TeamMemberName" />
<Field Name="Role" />
<Row>
<Field Name="TeamMemberName" Value="Bob" />
<Field Name="Role" Value="Developer" />
</Row>
<Row>
<Field Name="TeamMemberName" Value="Susan" />
<Field Name="Role" Value="Program Manager" />
</Row>
<Row>
<Field Name="TeamMemberName" Value="Jack" />
<Field Name="Role" Value="Test" />
</Row>
</Table>
<Table Name="Item List">
<Field Name="ItemName" />
<Field Name="Description" />
<Field Name="EstimatedHours" />
<Field Name="AssignedTo" />
<Row>
<Field Name="ItemName" Value="Learn SharePoint 2010" />
<Field Name="Description" Value="This should be fun!" />
<Field Name="EstimatedHours" Value="80" />
<Field Name="AssignedTo" Value=”All” />
</Row>
<Row>
<Field Name="ItemName" Value=
"Finalize Import Module Specification" />
<Field Name="Description" Value="Make sure to handle all document
formats." />
<Field Name="EstimatedHours" Value="35" />
<Field Name="AssignedTo" Value=”Susan" />
</Row>
<Row>
<Field Name="ItemName" Value="Write Test Plan" />
<Field Name=”Description" Value=
"Include regression testing items." />
<Field Name="EstimatedHours" Value="20" />
<Field Name="AssignedTo" Value="Jack" />
</Row>
</Table>
</ContentControls>
Figura 11 il documento generato
È possibile vedere che la riga singola contenente controlli contenuto è stata sostituita da più righe, ognuna contenente i dati di struttura ad albero XML è stato passato come argomento al metodo. Utilizza una struttura ad albero XML per passare i dati al codice che modifica il codice XML aperto, è possibile ottenere una separazione di codice che utilizza il modello a oggetti SharePoint e il codice di Open XML interessante.
Il codice per assemblare il nuovo documento rispetta qualsiasi formattazione applicata alla tabella. Ad esempio, se aver configurato la tabella per visualizzare colori diversi per le righe alterne o se è stato impostato il colore di sfondo di una colonna, il documento appena generato riflette le modifiche di formattazione.
Se si scarica ed esaminare l'esempio ContentControlManager, è possibile visualizzare che il codice ottiene una copia della riga che contiene i controlli contenuto e la salva in una riga di prototipo:
// Determine the element for the row that contains the content controls.
// This is the prototype for the rows that the code will generate from data.
XElement prototypeRow = tableContentControl
.Descendants(W.sdt)
.Ancestors(W.tr)
.FirstOrDefault();
Quindi, per ogni elemento recuperato da un elenco di SharePoint, il codice viene duplicato della riga di prototipo, modifica la riga duplicata con i dati dell'elenco SharePoint e aggiunge un insieme che viene inserito nel documento.
Dopo aver creato l'elenco di nuove righe, il codice rimuove la riga di prototipo dall'elenco e inserisce l'insieme di righe appena create, come illustrato di seguito:
XElement tableElement = prototypeRow.Ancestors(W.tbl).First();
prototypeRow.Remove();
tableElement.Add(newRows);
Creazione della funzionalità di SharePoint
Ho utilizzato la 2009 CTP di febbraio versione delle estensioni Visual Studio 2008 per Windows SharePoint Services 3.0, v1.3 per generare questo esempio. È stato creato ed eseguire questo esempio in versioni di sia a 32 e 64 bit di WSS. (Kirk Evans ha alcuni Webcast di grande illustrato l'utilizzo di queste estensioni).
L'esempio contiene il codice per creare i controlli Web Part. Il codice è piuttosto comprensibile se siete abituati alla creazione di Web part di SharePoint. Quando un utente fa clic il pulsante Genera Report, le chiamate di codice il metodo CreateReport, che assembla il nuovo documento di elaborazione testi di Open XML dal documento modello utilizzando i dati di SharePoint include un elenco configurato nei tag di controls.There il contenuto sono sul codice per il metodo CreateReport alcuni punti. I file in una raccolta documenti di SharePoint vengono restituiti come matrici di byte. È necessario convertire questa matrice di byte in un flusso di memoria in modo che sia possibile aprire e modificare il documento utilizzando il SDK di XML Apri. Uno dei costruttori MemoryStream accetta una matrice di byte e potrebbe essere tentati di utilizzare tale costruttore. Il flusso di memoria, tuttavia, creata con il costruttore è un flusso di memoria nonresizable e il SDK per Open XML richiede che il flusso di memoria sia ridimensionabile. La soluzione è creare un oggetto MemoryStream con il costruttore predefinito e quindi scrivere la matrice di byte da SharePoint in MemoryStream, come illustrato in figura 12.
Nella figura 12 scrittura di una matrice di byte da SharePoint a un flusso MemoryStream
private ModifyDocumentResults CreateReport(SPFile file, Label message)
{
byte[] byteArray = file.OpenBinary();
using (MemoryStream mem = new MemoryStream())
{
mem.Write(byteArray, 0, (int)byteArray.Length);
try
{
using (WordprocessingDocument wordDoc =
WordprocessingDocument.Open(mem, true))
{
// Get the content control structure from the template
// document.
XElement contentControlStructure =
ContentControlManager.GetContentControls(wordDoc);
// Retrive data from SharePoint,
constructing the XML tree to
// pass to the ContentControlManager.SetContentControls
// method.
...
}
}
}
}
Il resto del codice è semplice. Utilizza il modello a oggetti SharePoint per recuperare le raccolte documenti e il contenuto delle librerie, recuperare gli elenchi e recuperare valori di colonne per ogni riga nell'elenco. Struttura ad albero XML per passare a ContentControlManager.SetContentControls assembla e quindi chiama SetContentControls.
Il codice assembla il nome del documento rapporto generato come report-aaaa-mm-dd. Se il report esiste già, il codice aggiunge un numero al nome del report per evitare ambiguità tra il rapporto da altri rapporti che sono già stati generati. Ad esempio, se 01.docx 08 di 2009 report esiste già, il rapporto viene scritto con estensione docx report-2009-8-2 (1).
Personalizzazione semplice
Sarà probabilmente necessario personalizzare questo esempio in base alle proprie esigenze. Un possibile miglioramento consiste nel consentire per un controllo contenuto nel corpo del documento modello che estrae il contenuto di standard di un documento specificato archiviato in SharePoint. È possibile scrivere il codice in modo che è possibile inserire il nome del documento che contiene il testo standard come testo nel controllo contenuto.
Inoltre, questo esempio rigido-codici i nomi di TemplateReports e le librerie di documento del report. È possibile rimuovere questo vincolo necessario specificare queste informazioni in un elenco di SharePoint. Il codice sarebbe quindi sapere che il nome di questo elenco di configurazione. I nomi di TemplateReports e le librerie di documento del report dovrebbe dipendere dai dati dall'elenco configurazione.
SharePoint è una tecnologia potente che rende più semplice per gli utenti nelle organizzazioni di collaborare. XML aperto è una potente tecnologia di emergente che modifica la modalità che è possibile generare documenti. Utilizzo congiunto di due tecnologie consente di creare applicazioni per collaborare in nuovi modi in cui persone possibile utilizzare i documenti.
Eric White un writer in Microsoft è specializzato nei formati di file Office Open XML, Office e SharePoint. Prima di unirsi a Microsoft nel 2005, ha lavorato come uno sviluppatore per un numero di anni e quindi avviato PowerVista Software, una società che sviluppato e venduto un oggetto widget griglia multipiattaforma. Ha scritto libri su controllo personalizzato e lo sviluppo di GDI+. Leggere il suo blog all' blogs.msdn.com/ericwhite di.