05/08/2013 - 'User' issue in SharePoint 2007 Solved
Based on the 05/07/13 hunch, my tests today show that it works as described when "Name (with presence)" is selected in the 'Show Field' of the Site Column
05/07/2013 - I think I figured out why 'User' didn't work:
In the site column there is an option for "Show Field". Even though the field datatype was Person or Group, I had only selected "Name", not "Name (with presence)". I discovered this when trying to display the data in a different webpart, and the hyperlinked word didn't show.
I haven't tested this, but will do so when I get time.
05/02/2013 - Finished making a prototype for SharePoint 2010. Here are some new facts:
1. The <CommonViewFields> does NOT need to be populated in order to show data. My property is completely blank, but I can access ALL data from the list. (Don't know if this is a good thing or not, but it's the way it is.)
2. The "User" datatype problem that I had in SharePoint 2007 is not a problem in 2010!!!!!!!
05/01/2013 - Today I finished a proof of concept in SharePoint 2010. For the most part, I had to recreate everything from scratch, using all the same techniques specified below. There is some new code in 2010 that I made sure not to touch as I implemented the custom code. The takeaway there is that you can't copy and paste from 2007 to 2010, you must implement specific lines of code.
I had hoped to never have to learn this much about a Content Query Web Part (CQWP), but the organization decided to stop using a well-known aggregation platform, also known as CorasWorks. So, in an attempt to remediate all of the pages that depend on the CorasWorks grid, I stepped into an already-in-progress project that required the use of a CQWP. Personally, I think I would have preferred to scrap it all and start over with a Data View Web Part (DVWP), but after spending 40 hours constructing this thing, I might as well tell you about it.
First thing I need to do is to thank everyone in the "Credits" section at the bottom of this article. Without all of those people posting their golden nuggets, then you wouldn't be reading this. They paved the muddy trail, and made it such that my boots stayed clean. If you're just starting, my guess would be that you've encountered these great people in your web searches, so please take the time to read/watch them, and give them their due.
Regarding the topic, I doubt that you'll grab it all the first time. If you're like me, you'll need to read an article a couple of times (including this one) as it may not make sense the first time you read it. Reading and re-reading it numerous times will happen. I know I did.
Thanks for reading. Feel free to post questions / comments as I'll try hard to respond.
Select a Content Type
First things first.
Learning the basics of the CQWP is the first step, and understanding how you can aggregate data, will make this exercise easier for you. You see, the way that a CQWP can compile data from across multiple sites is by instructing it to look for a certain Content Type. So, if you use a generic Content Type, like Task, then you'll end up pulling EVERY task list throughout your scope. This will probably not be desired, so to overcome this, you can make a Custom Content Type. Once created, you can make lists throughout your scope, and when you instruct the CQWP to look for it, then you'll only get your custom list content.
Creating a Custom Content Type
For this, I went to the Site Collection's Site Content Type Gallery (/_layouts/mngctype.aspx) and created a new Content Type. I used all new Site Columns, ensuring that no spaces or other special characters were in the field names. Spaces will eventually result in having to use some dreaded character string, like "_x0020x_", which just makes your job harder. So, don't use spaces or #, %, $, etc.
Next, I created a custom list based on the "Custom List" template. Edit the setting of the list, and added my new Content Type to the list, such that I had all of the fields needed for display in the CQWP. Once I finalized that model list, I saved that list as a new List Template, for use throughout the Site Collection. For my proof of concept, I did make a couple of sites and put my new list in it, but you can also just make a bunch of lists in a single site, and they'll get picked up by the CQWP as well. (Just makes it easier when your time crunched.)
With the infrastructure ready to go, make a "Base" CQWP in preparation to customize it. (Many of the other articles cover this step-by-step, so I've shortened it to save the bandwidth.)
Create a Web Part Page, add a CQWP
Make all the selections needed to get data to show from your disparate list locations. (The big trick at this point is to select the new Custom Content Type. See pic.)
Export your new CQWP for customizing.
Open in SharePoint Designer or other editor that will help with XML based files. (I did it all in SPD.)
To add your custom fields for output through your custom CQWP, you must update the ViewCommonFields property. It is blank when you first export it, like this:
Here are a couple of things that I wasted time researching:
The type="string" means nothing, so ignore it. Don't touch it, you can only break it.
Each Fieldname,DataType; pairing has a comma between them, not a dot. Ensure you don't fat finger it.
Use a semi-colon if you want another pairing after it. You can have a semicolon before the closing property tag, and it won't cause an error.
*TIME / FRUSTRATION SAVER ALERT*
Add each field only one at a time! Save your webpart, import it into the Gallery, then add an instance to your page and see if it works. Debugging these files is a complete PITA because there is no way to test it prior to using it. If you put all of the fields, and one of them is bogus, then you'll have to do this technique anyway.
Also, adding the fields to this property does NOT make them render in your custom webpart. It only makes them available for output. Until you update the ItemStyle.xsl, they will NOT show.
You'll see in my code, later, that I have it as "GPM,Text" but it doesn't return anything, and for now, I'm hardcoding a value for that field in my ItemStyle.xsl for output. If you know how to fix it, please chime in.
It's worth noting that if you need to rename columns, then look for the DataColumnRenames property. I did not use it, but the other bloggers have covered this in detail.
My entire .webpart file is below, which is probably overkill, but enjoy.
Customize the ItemStyle.xsl
As stated previously, just updating the .webpart file to include your fields does NOT allow them to display, it only sets up the infrastructure. So, the first thing to do to ItemStyle.xsl is to make a view that displays ALL of the data that is available to you.
So, look at the example code below and locate the Template called "ShowXML". Copy and paste that into the bottom of your ItemStyle.xsl file. (This does customize or unghost your file, but gotta do what you gotta do.) Publish it as a major version, just know that you're affecting your entire Site Collection, so if you botch this, your phone might ring... like immediately. (No pressure, because at worst, you can select "Reset to site definition, and all will be well again.)
In the case it works, you will see something like this:
(Some data has been altered to protect the innocent)
The output is sorted in alphabetical order, so your field names will be interspersed with the core data, like Author, ImageURL and Style.
So, what this is telling you are the fields that are available to be displayed. If you don't see it here, you can't output it later. (Again, notice that my GPM field is blank, and I still need help with it. Somebody please help me.)
In the hockey stick learning curve that this article presents, you have now reached the end of the puck-striking end, and you are about to scale upwards toward the gripping end. Again, I would advise that you understand the topics covered in the Credits section, which will reduce the dramatic curve.
Use the existing templates, and guidance from the other articles to create a simple output, which will do things like:
Output the content to a table... GROUPED!
In the credits below, Paul Galvin's article describes how to output information in table form. He taps into when to start the table, and more importantly, when to end it. This works with relative ease, and with some formatting, you can make it as pretty as you need. (This is why all of my code has id tags with it. I was working with a great stylesheet guy that told me what to put and where, I just followed suit.)
Unfortunately, I need my data to be grouped, and then also output in table form. So, after spending time just getting the table created, the next thing was to focus on producing it for each Group.
If you look in my ContentQueryMain.xsl code, you will find the following:
What this does is creates a variable called GridPMOTableEnd. If the current style being applied is my "GridPMO", as defined in my ItemStyle.xsl, then it adds the HTML code to end the table. Then, I use a regular select to get the value from the variable, but also use the disable-output-escaping such that it doesn't convert "<" to < and the like.
Also in the ContentQueryMain, you'll see that I followed Paul's lead and passed a parameter for the StartNewGroup (which is already part of the code.). I'm going to admit that don't understand fully how this works, but I appreciate the gift horse. Look through the code and you'll see StartNewGroup and StartNewGrp. (Enjoy!)
In ItemStyle.xsl, I then make a variable for the tableStart, and call the variable just like I did for the tableEnd (in ContentQueryMain.xsl)
This is what converted my dates from YYYY-MM-DD to how they look now. The 1033 is American English, and the 1 is the desired format.
It is important to know that the following code must be added to the top of the file in order to call the function:
xmlns:ddwrt="http : // schemas.microsoft.com/WebParts/v2/DataView/runtime" (Spaces added intentionally to the above url.)
(If the link above this line has StrikeThrough applied, do not assume that it is a broken link, nor incorrect. Since this is a reference to a code library, I don't know that HubPages knows how to deal with it. Here it is broken down: schemas dot Microsoft dot com / webparts / v2 / dataview / runtime
If you look at the top picture, you can see that there are multiple tabs, each with different status, and has you can imagine, a different CQWP on each tab.
The magic here is the use of Easy Tabs. Implement their code, then make an instance of your CQWP, with the proper filters, on the web part page. Easy Tabs are implemented as code in a Content Editor Web Part (we reference a file in a library, vice posting the code with the CEWP), and everything above that CEWP gets made into a tab. It's very slick.
With that, Brave Coder, I wish you luck and good health with your Custom CQWP. Be patient, make small code changes, and deploy, such that debugging and/or rolling back are not so tedious and painful.
All of my code is below for full review, and I hope it prevents a few wasted hours on your part, as there was on mine.
Thanks for reading!
Steve Clark Twin-Soft Corporation Easy Bins Dumpster Rentals Independent Consultant
ItemStyle.xsl Custom Templates
Web Part XML
If you're just starting to learn how to create your own custom CQWP, then here's all the sources that I found to be helpful. They're not ordered any particular way, but thanks to all of these folks for paving the muddy path for me. I couldn't have done it without them.