Programatically change metadata across all data on all SPList objects in WSS

Refer to blogs.msdn.com/dwinter/archive/2005/02/15/373076.aspx for setup if you are not familiar with creating a SharePoint OM application.

This is a simple example of programatically changing metadata on data within all lists in a site. This can be necessary if you wish to change static data within custom or default fields, or perhaps to adjust a migration gone wrong.

This function requires:

  • a listbox named errorBox (which I'm logging errors/etc to)
  • one textbox named siteName to define where our lists are
  • two textboxes for input called oldValue and newValue
  • a button called replaceBtn.

You can pretty-up the interface however you want beyond this and you should be able to drop this code in place. You'll want to register the button click to match this function. This code specifically may not be viable for a production or large environment due to the ammount of data being parsed and the possible risk involved. If this is the case, it would be more useful to enumerate the list objects into perhaps a listbox and allow for selection of specific lists. Additionally, you could enumerate the data of the selected lists into another listbox and allow for specific data selection to reduce risk of changing something you do not want changed. As far as I know you would still need to enumerate everything at least once, but with production data, you always want to be careful not to change data accidently. This particular kind of code is dangerous because it is doing a large loop that touches everything and it has the potential to change items that you may not want (or even know about) to be changed. Due to this, I'll stick to the old addage of test, test, test, and then test some more, and then go to production.

You may notice that I'm specifically logging errors and providing an Edit URL as a part of the error logging (you may want to add a button with a function to take the errorBox contents to a log file or webpage to utilize those URLs. Then of course you may ask why I put the extra attention in looking for errors like this instead of just catching them and making a simple log entry. The reason is that not all metadata is writable. Because of this, I want to pay special attention to what is not changable. I have encountered a few situations where programatically the metadata could not be changed--but if I went through the webUI manually (hence the edit link), it could be.

private

void replaceBtn_Click(object sender, System.EventArgs e)
{
int replaceNumber=0;
int errorNumber=0;
SPSite mySite = new SPSite(siteName.Text);
foreach(SPList mySPList in mySite.OpenWeb().Lists)
{
foreach(SPListItem mySPLI in mySPList.Items)
{
try
{
foreach(SPField mySPField in mySPLI.Fields)
{
string tempOld="";
try
{
tempOld = mySPLI[mySPField.Title].ToString();
}
catch{}
try
{
if(mySPLI[mySPField.Title].ToString().IndexOf(oldValue.Text) > -1)
{
mySPLI[mySPField.Title]=mySPLI[mySPField.Title].ToString().Replace(oldValue.Text,newValue.Text);mySPLI.Update();
replaceNumber++;
errorBox.Items.Add(mySPField.Title+" -Old: "+tempOld+" -New: "+mySPLI[mySPField.Title]);
}
}
catch(System.NullReferenceException nex){}
catch(Exception ex)
{
errorBox.Items.Add("Error on: "+mySPLI.ID+" in Title="+ex.Message);
errorBox.Items.Add("Tried to change "+oldValue.Text+" to "+newValue.Text+" and failed. Manually change using: ");
errorBox.Items.Add(mySPList.ParentWeb.Url.Substring(0,mySPList.ParentWeb.Url.IndexOf("/",8))+mySPLI.ParentList.DefaultViewUrl.Substring(0,mySPLI.ParentList.DefaultViewUrl.LastIndexOf("/"))+"/EditForm.aspx?ID="+mySPLI.ID);
errorNumber++;
}
}
}
catch{}
}
}
errorBox.Items.Add("Replaced "+replaceNumber+" items");
errorBox.Items.Add("Failed to replace "+errorNumber+" items");
}