none
How to delete Orphaned Workflow Status Columns from SharePoint List Views RRS feed

  • Question

  • In SharePoint 2010, I have created some workflows using SharePoint designer and attached them to the list. I noticed the duplicate workflow status columns in the "All Items" view of the list. How can I delete these Orphaned Workflow Status Columns from the list?
    Tuesday, March 20, 2012 8:03 PM

All replies

  • Hi Sharester.

    Check this:

    Delete Orphaned Workflow Status Columns from SharePoint List Views
    http://nikspatel.wordpress.com/2010/08/07/delete-orphaned-workflow-status-columns-from-sharepoint-list-views/

    Sharepoint 2010 Orphaned Workflows
    http://bradleychetty.blogspot.se/2011/08/sharepoint-2010-orphaned-workflows.html

    and same theme:
    auto remove orphaned workflows in SP 2010
    http://social.msdn.microsoft.com/Forums/is/sharepoint2010general/thread/da1e42bc-7f2a-494e-983d-ed9d3a22947b

    Any help?

    Regards


    Thomas Balkeståhl - Technical Specialist - SharePoint - http://blog.blksthl.com
    Download the SharePoint Branding Project here

    Tuesday, March 20, 2012 8:40 PM
  • Hi Thomas

    Thanks for your reply.

    As per the 2nd solution, I deleted all the contents from the recycle bin but it still shows the duplicate workflow status columns. does it depend on any clean up job?

    Wednesday, March 21, 2012 1:40 PM
  • Hi ,

    You can try to modify the list view to uncheck the workflow name column .

    Thanks



    Entan Ming

    TechNet Community Support

    Thursday, March 29, 2012 2:40 AM
    Moderator
  • I ran into this issue myself, and unfortunately, there didn't seem to be an easy way for me to delete the field, since I couldn't use PowerShell, being that my client was on Sharepoint Online (Office 365). I also didn't want to have to write, package, and deploy a sandboxed solution just to handle this. In the end, I ended up writing a javascript function to automate the process for me from the browser's console. It uses the Sharepoint Client Object model. Figured I'd share it, just in case anyone else was facing the same limitations:

    /**
     * @projectDescription	An anonymous function, to be run from the browser's console on a
     *						Sharepoint 2010 List View page. (For instance,
     *						http://site/Lists/MyList/AllItems.aspx) The original purpose was to
     *						delete Workflow Status fields that remained after removing a list
     *						workflow.
     *
     * @author				Charles Grunwald (Juntalis) ch@rles.grunwald.me
     * @version				0.1
     */
    (function () {
    	//  Highlevel local variables.
    	var w = window,
    	su = SP.ScriptUtility,
    	hu = SP.Utilities.HttpUtility,
    	// Simple class to allow shorter calls when using
    	// some of the Sharepoint Client Object stuff.
    	$P = {
    		err : function() {	for(var i=0;i<arguments.length;i++) console.error(arguments[i]); },
    		log : function() {
    			for(var i=0;i<arguments.length;i++) {
    				var o = arguments[i];
    				if(typeof o === "object") {
    					console.dir(o);
    				} else {
    					console.log(o);
    				}
    			}
    		},
    		noop : function() {},
    		undef : function (o) { return su.isUndefined(o); },
    		def : function (o) { return !su.isNullOrUndefined(o); },
    		empty : function (s) { return su.isNullOrEmptyString(s ); },
    		floor : function (o) { return su.truncateToInt(o); },
    		enc : {
    			html : function(o) { return hu.htmlEncode(o); },
    			js : function(o) { return hu.ecmaScriptStringLiteralEncode(o); },
    			xml : function(o) { return hu.escapeXmlText(o); },
    			url : function(o) { return hu.urlKeyValueEncode(o); },
    			http : function(o) { return hu.urlPathEncode(o); }
    		},
    		target : null,
    		trim : window.TrimSpaces,
    		list : null,
    		fields : {},
    		listTitle : null,
    		web : null,
    		ctx : new SP.ClientContext(L_Menu_BaseUrl),
    		site : L_Menu_BaseUrl
    	};
    	
    	// Add some extra utility functions to SPContext to make it
    	// easier to work with.
    	(function (t) {
    		(function (c) {
    			c.r = [];
    			c.q = function () {
    				var _e = function (a, b) {
    					console.error("An error occurred with executing a query.");
    					console.dir(b);
    					throw b;
    				};
    				var _a = arguments;
    				var _l = _a.length;
    				var _d = Function.createDelegate;
    				if (_l === 0) {
    					c.executeQueryAsync(_d(t, t.noop), _d(t, _e));
    				} else if (_l === 1) {
    					c.executeQueryAsync(_d(t, _a[0]), _d(t, _e));
    				} else if (_l === 2) {
    					c.executeQueryAsync(_d(t, _a[0]), _d(t, _a[1]));
    				} else {
    					c.executeQueryAsync(_d(_a[0], _a[1]), _d(_a[0], _a[2]));
    				}
    				return c;
    			};
    			c.l = function () {
    				var _a = arguments;
    				var _l = _a.length;
    				var _f = function (_A) {
    					c.r = [];
    					for (var i in _A) {
    						c.load(_A[i]);
    						c.r.push(_A[i]);
    					}
    				};
    				if (_l > 1) {
    					_f(_a);
    				} else if (_l == 1) {
    					_a = _a[0];
    					if (t.def(_a["get_$h"])) {
    						c.load(_a);
    						c.r = _a;
    					} else if (t.def(_a["getEnumerator"])) {
    						var _e = _a.getEnumerator();
    						c.r = [];
    						while (_e.moveNext()) {
    							var i = _e.get_current();
    							c.r.push(i);
    							c.load(i);
    						}
    					} else {
    						_f(_a);
    					}
    				}
    				return c;
    			};
    			c.lq = function (l, q) {
    				c.l.apply(c, l);
    				c.q.apply(c, q);
    				return c;
    			};
    			c.lists = (c.web = c.get_web()).get_lists();
    			c.list = {};
    			(function (l) {
    				var _idcache = {};
    				var _tcache = {};
    				l.byid = function (i) {
    					if (!t.def(_idcache[i]))
    						_idcache[i] = c.lists.getById(i);
    					return _idcache[i];
    				};
    				l.bytitle = function (i) {
    					if (!t.def(_tcache[i]))
    						_tcache[i] = c.lists.getByTitle(i);
    					return _tcache[i];
    				};
    			})(c.list);
    		})(t.ctx);
    		t.web = t.ctx.web;
    	})($P);
    	
    	function main() {
    		// Validate that we have a field name.
    		if(arguments.length === 0 || $P.empty(arguments[0])) {
    			console.error("No field name specified.");
    			return new Error("Unknown Field");
    		}
    		$P.target = arguments[0];
    		
    		// Set up our list title.
    		$P.listTitle = (arguments.length > 1) && (arguments[1].length > 0) ?
    			arguments[1] : resolveListName();
    		if (!$P.listTitle || $P.listTitle.length < 0) {
    			console.error("Failed to resolve list title and none specified.");
    			return new Error("Unknown List");
    		}
    		
    		// Load our list and it's associated fields.
    		$P.log("Working on list: " + $P.listTitle);
    		loadList($P.listTitle);
    		return "Querying list & field information..";
    	}
    	
    	function resolveListName() {
    		var result = w.location.pathname;
    		return (
    			result = result
    				.substr(
    					0,
    					result.lastIndexOf("/"))).substr(
    			result.lastIndexOf("/") + 1);
    	}
    	
    	function loadList(l) {
    		$P.list = $P.ctx.list.bytitle(l);
    		var fields = $P.list.get_fields();
    		
    		$P.ctx.l($P.list, fields).q(function(sender, args) {
    			var enumerator = fields.getEnumerator();
    			while (enumerator.moveNext()) {
    				var field = enumerator.get_current();
    				$P.fields[field.get_staticName()] = field;
    			}
    			$P._fields = fields;
    			$P.ctx.q(deleteField);
    		});
    	}
    	
    	function deleteField(sender, args) {
    		$P.log("Attempting to remove read-only property from field.");
    		if($P.undef($P.fields[$P.target])) {
    			$P.err("Field " + $P.target + " does not exist in this context.");
    			throw new Error("Invalid Field");
    		}
    		var field = $P.fields[$P.target];
    		field.set_readOnlyField(false);
    		field.update();
    		
    		$P.ctx.l(field, $P._fields).q(function(s,a) {
    			$P.log(
    				"Attempting to delete field.",
    				"If you receive an error indicating you need to use the web interface to delete "+
    				"the field, you can most likely safely ignore it. Not sure why it throws that "+
    				"error, but the function seems to execute fine."
    			);
    			field.deleteObject();
    			field.update();
    			$P.ctx.l(field, $P._fields).q(function() {
    				$P.log("All done.");
    			});
    		});
    	}
    	
    	return main.apply(this, arguments);
    })(
    	/* Your field name. */
    	"Recent_x0020_Updates"
    	/*
    	Optionally, you can also specify the List Title like so:
    	
    	, "MyList"
    	
    	Note: If no list title is specified, the script will attempt to
    	auto-resolve the title from the current url.
    	*/
    );

    If you have any questions, feel free to ask. I also threw it into a gist for simplicity-sake.
    Friday, May 11, 2012 7:58 AM
  • Hi Charles.  I would love to do this, but don't have any experience with code, etc.  Is it possible to lay out the steps to run this or is it too complicated without the proper experience?

    Cam

    Tuesday, June 5, 2012 4:34 PM
  • Hey Cam,

    Bit swamped with work at the moment, but I'll try to put together a tutorial in the next couple of days. I'm going to need to write a secondary script, I think, to get the internal names of the fields, since most of the Workflow Status fields seem to only contain 8 letters from the name you give it. (For instance, my workflow ProjectActions's real name is actually ProjectA)

    Monday, June 11, 2012 2:16 PM
  • Excuse the double post, but I wanted to make sure Cam got a notification.

    I had some time to my own devices today, so I went ahead and added to the earlier script. Unfortunately, I don't have much time to test the script, but from the testing I did do, it should work. Additionally, due to a few mistakes I made, the script will only work in IE9/Chrome/Firefox. When I have more time, I'll go back and fix it to work with IE8 and IE7. If you have any problems, feel free to email me or respond here and I'll do what I can to help. I updated the gist linked earlier, and here's the new source (Instructions on how to use it below):

    // ==ClosureCompiler==
    // @output_file_name delete-sp2010-field.js
    // @compilation_level SIMPLE_OPTIMIZATIONS
    // ==/ClosureCompiler==
    
    /**
     * @projectDescription    An anonymous function, to be run from the browser's console on a
     *                        Sharepoint 2010 List View page or Form. (For instance,
     *                        http://site/Lists/MyList/AllItems.aspx) The script creates a UI
     *                        that lists all Workflow Status fields and allows for the easy
     *                        removal of these fields. (By removing the ReadOnly flag on the field,
     *                        and then removing it) A bookmarklet version of this script can be found at:
     *
     *                        http://charles.grunwald.me/code/spfieldremove.html
     *
     *                        The core functionality was written during development on a Sharepoint Online
     *                        project, and then extended on to provide a simple solution for following forum question:
     *
     *                        http://social.technet.microsoft.com/Forums/en-US/sharepoint2010customization/thread/613a9a71-7a8e-4769-9fe6-cbb65ac06b4a/#9e660621-ba12-4b3f-804f-139a57b1f1ae
     *
     * @author                Charles Grunwald (Juntalis) ch@rles.grunwald.me
     * @version                0.3
     */
    
    (function (window) {
    	//  High-level local variables.
    	var w = window,
    	doc = w.document,
    	body = (typeof doc['body'] === 'undefined') ? doc.getElementsByTagName('body')[0] : doc.body,
    	ctx = (typeof ctx === 'undefined') ? ((typeof _spPageContextInfo === 'undefined') ? null : _spPageContextInfo) : ctx,
    	/* Just realized the following two namespaces aren't always loaded, so I'll just substitute
    	my own definitions if they don't already exist. */
    	su = (typeof SP['ScriptUtility'] !== 'undefined') ? SP.ScriptUtility : (function (su) {
    		// To maintain compatibility with IE7, I need to declare it like this.
    		su.isUndefined = function (x) { return (typeof(x) === 'undefined') || (x == undefined); };
    		su.truncateToInt = function (x) { return new Number(Math.floor(x)); };
    		su.isNullOrUndefined = function (x) { return su.isUndefined(x) || (x == null); };
    		su.isNullOrEmptyString = function (x) { return su.isNullOrUndefined(x) || su.isUndefined(x.length) || (x.length === 0); };
    		return su;
    	})({}),
    	hu = (!su.isNullOrUndefined(SP['Utilities'])) && (!su.isNullOrUndefined(SP.Utilities['HttpUtility'])) ? SP.Utilities.HttpUtility : (function (hu) {
    		hu.htmlEncode = function (x) {
    			// Slightly modified from:
    			// http://stackoverflow.com/questions/4742600/what-is-the-most-simple-javascript-htmlencode-lib-function-implementation
    			// Not a real htmlEncode, but it'll work for our needs.
    			var r = '';
    			var allowedChars = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
    
    			for(var i = 0; i < x.length; i++) {
    				var ch = x.charAt(i);
    				var chCode = x.charCodeAt(i);
    				if(isNaN(chCode)) { continue; }
    				if(allowedChars.indexOf(ch) > -1) { r += ch; }
    				else { r += '&#' + chCode + ';'; }
    			}
    			return r;
    		};
    		// Since our htmlEncode function is actually an xmlEncode function.
    		hu.escapeXmlText = function (x) { return hu.htmlEncode(x); };
    		hu.urlKeyValueEncode = function (x) { return w.encodeURIComponent(x); };
    		hu.urlPathEncode = function (x) { return w.encodeURI(x); };
    		// Haven't really used this function and don't have time to reverse engineer it, so I'll just use this.
    		hu.ecmaScriptStringLiteralEncode = function (x) { x.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); };
    		return hu;
    	})({}),
    
    	// Our console object.
    	console = (!su.isNullOrUndefined(w.console)) ? w.console : (function (console) {
    		console.log = function () { /* If we don't have a console, this is kind of pointless. */ };
    		// To avoid 20 alert boxes, I'm combining it into one message.
    		console.error = function () {
    			var m = "";
    			for(var i = 0; i < arguments.length; i++) { m += arguments[i]; }
    			alert(m);
    		};
    		console.dir = function () { /* If we don't have a console, this is kind of pointless. */ };
    		return console;
    	})({}),
    
    	// Simple class to allow shorter calls when using
    	// some of the Sharepoint Client Object stuff.
    	$P = (function ($P) {
    			$P.ui = {};
    			$P.err = function () {
    				var conErr = function() {
    					if(!$P.def(w.console)) {
    						if(!$P.def($P.ui['err'])) {
    							console.error.apply(this, arguments);
    						}
    					} else {
    						for(var i = 0; i < arguments.length; i++) {
    							console.error(arguments[i]);
    						}
    					}
    				}
    
    				if($P.def($P.ui['err'])) {
    					$P.ui.err.apply($P.ui, arguments);
    				}
    				conErr.apply($P, arguments);
    			};
    			$P.log = function () {
    				if(!$P.def(w.console)) { return; }
    				for(var i = 0; i < arguments.length; i++) {
    					var o = arguments[i];
    					if(typeof o === 'object') {
    						console.dir(o);
    					} else {
    						console.log(o);
    					}
    				}
    			};
    			$P.info = function () {
    				if($P.def($P.ui['info'])) {
    					$P.ui.info.apply($P.ui, arguments);
    					$P.log.apply($P, arguments);
    				} else {
    					$P.log.apply($P, arguments);
    				}
    			};
    			$P.noop = function () {};
    			$P.undef = function (o) { return su.isUndefined(o); };
    			$P.def = function (o) { return !su.isNullOrUndefined(o); };
    			$P.empty = function (s) { return su.isNullOrEmptyString(s); };
    			$P.floor = function (o) { return su.truncateToInt(o); };
    			$P.enc = {};
    			$P.enc.html = function (o) { return hu.htmlEncode(o); };
    			$P.enc.js = function (o) { return hu.ecmaScriptStringLiteralEncode(o); };
    			$P.enc.xml = function (o) { return hu.escapeXmlText(o); };
    			$P.enc.url = function (o) { return hu.urlKeyValueEncode(o); };
    			$P.enc.http = function (o) { return hu.urlPathEncode(o); };
    			// Again, not defined on every page, so..
    			$P.trim = ($P.def(w['TrimSpaces'])) ? w.TrimSpaces : function (s) { return s.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };
    			$P.list = null;
    			$P.fields = {};
    			$P.listTitle = null;
    			$P.listId = null;
    			$P.site = (function(){
    				if($P.def(L_Menu_BaseUrl)) {
    					return L_Menu_BaseUrl;
    				} else if($P.def(ctx)) {
    					if($P.def(ctx['HttpRoot'])) {
    						return ctx.HttpRoot.substr(w.location.protocol.length + w.location.hostname.length + 2);
    					} else if($P.def(ctx['webServerRelativeUrl'])) {
    						return ctx.webServerRelativeUrl;
    					}
    				} else {
    					var url = w.location.pathname;
    					url = url.substr(0, url.lastIndexOf('/'));
    					var idx = url.lastIndexOf('/Lists');
    					if(idx === -1) {
    						return url.substr(0, url.lastIndexOf('/'));
    					} else {
    						return url.substr(0, idx);
    					}
    				}
    			})();
    			$P.client = new SP.ClientContext($P.site);
    			$P.web = $P.client.web;
    			return $P;
    		})({});
    
    	// Add some extra utility functions to SPContext to make it
    	// easier to work with.
    	(function (client) {
    		client.lastResult = [];
    		client.q = function () {
    			var errFunc = function (sender, args) {
    				$P.err('An error occurred with executing a query.');
    				$P.log(args);
    				throw args;
    			};
    			var argLen = arguments.length;
    			var funcDel = Function.createDelegate;
    			if(argLen === 0) {
    				client.executeQueryAsync(funcDel($P, $P.noop), funcDel($P, errFunc));
    			} else if(argLen === 1) {
    				client.executeQueryAsync(funcDel($P, arguments[0]), funcDel($P, errFunc));
    			} else if(argLen === 2) {
    				client.executeQueryAsync(funcDel($P, arguments[0]), funcDel($P, arguments[1]));
    			} else {
    				client.executeQueryAsync(funcDel(arguments[0], arguments[1]), funcDel(arguments[0], arguments[2]));
    			}
    			return client;
    		};
    		client.l = function () {
    			var argLen = arguments.length;
    			var storeResults = function (args) {
    				client.lastResult = [];
    				for(var i = 0; i < args.length; i++) {
    					client.l(args[i]).lastResult.push(args[i]);
    				}
    			};
    			if(argLen > 1) {
    				storeResults(arguments);
    			} else if(argLen === 1) {
    				var arg = arguments[0];
    				if($P.def(arg)) {
    					if($P.def(arg['get_$h'])) {
    						client.load(arg);
    						client.lastResult = arg;
    					} else if($P.def(arg['getEnumerator'])) {
    						var enumerator = arg.getEnumerator();
    						client.lastResult = [];
    						while(enumerator.moveNext()) {
    							var i = enumerator.get_current();
    							client.lastResult.push(i);
    							client.load(i);
    						}
    					} else {
    						storeResults(arg);
    					}
    				}
    			}
    			return client;
    		};
    		client.lq = function (l, q) {
    			client.l.apply(client, l);
    			client.q.apply(client, q);
    			return client;
    		};
    		client.lists = (client.web = client.get_web()).get_lists();
    		client.list = (function (list) {
    			var idCache = {};
    			var titleCache = {};
    			list.byid = function (idVal, callback) {
    				var id, idStr;
    				if(!$P.def(idVal['ToSerialized'])) {
    					id = new SP.Guid(idVal);
    				} else {
    					id = idVal;
    				}
    				idStr = id.toString('D');
    				if(!$P.def(idCache[idStr])) {
    					idCache[idStr] = client.lists.getById(idVal);
    				}
    				$P.client.l(idCache[idStr]).q(function(){
    					titleCache[idCache[idStr].get_title()] = idCache[idStr];
    					if($P.def(callback)) {
    						callback.apply(this, arguments);
    					}
    				});
    				return idCache[idStr];
    			};
    			list.bytitle = function (title, callback) {
    				if(!$P.def(titleCache[title])) {
    					titleCache[title] = client.lists.getByTitle(title);
    				}
    				if($P.def(callback)) {
    					$P.client.l(titleCache[title]).q(function(){
    						idCache[titleCache[title].get_id().toString('D')] = titleCache[title];
    						if($P.def(callback)) {
    							callback.apply(this, arguments);
    						}
    					});
    				}
    				return titleCache[title];
    			};
    			return list;
    		})({});
    	})($P.client);
    
    	// Our entry point.
    	function main() {
    		// Before going any further, let's build our gui.
    		buildGui($P.ui).info('Resolving our list..');
    		// Resolve our list.
    		resolveList(function (list) {
    			if(!$P.def(list)) {
    				$P.err(
    					'Failed to resolve list title. You may want to try going to the default view of ' +
    						'the list you want to work on.'
    				);
    				throw new Error('Unknown List');
    			}
    			$P.info('Resolved current list to ' + $P.listTitle);
    
    			// Load our list and it's associated fields.
    			$P.info('Querying list information..');
    			loadListFields($P.listTitle);
    		});
    		return $P;
    	}
    
    	// Try to resolve our list name. Checks for different context variables present on forms, views, etc. If we can't
    	// find those, we'll use resolveByUrl
    	function resolveList(callback) {
    		var list;
    		if($P.def(ctx)) {
    			if($P.def(ctx['ListTitle'])) {
    				$P.listTitle = ctx.ListTitle;
    				list = $P.client.list.bytitle(ctx.ListTitle, function(){
    					$P.listId = list.get_id();
    					callback($P.list = list);
    				});
    			} else if($P.def(ctx['pageListId'])) {
    				$P.listId = new SP.Guid(ctx.pageListId);
    				list = $P.client.list.byid($P.listId, function(){
    					$P.listTitle = list.get_title();
    					callback($P.list = list);
    				});
    			}
    		} else {
    			resolveByUrl(callback);
    		}
    	}
    
    	// This function is pretty much guaranteed to find the list associated with the current URL. It does, however,
    	// assume that you're at a page in your list's root folder (ex: /Path/leading/up/to/Lists/MyList/Page.aspx)
    	function resolveByUrl(callback) {
    		var url = w.location.pathname;
    		url = url.substr(0, url.lastIndexOf('/'));
    		$P.client.l($P.client.lists).q(function () {
    			var lists = [];
    			var enumerator = $P.client.lists.getEnumerator();
    			while(enumerator.moveNext()) {
    				var list = enumerator.get_current();
    				lists.push(list);
    				$P.client.l(list);
    			}
    			$P.client.q(function () {
    				var folders = [];
    				for(var i = 0; i < lists.length; i++) {
    					var list = lists[i];
    					var folder = list.get_rootFolder();
    					folders.push(folder);
    					$P.client.l(folder);
    				}
    				$P.client.q(function () {
    					for(var i = 0; i < folders.length; i++) {
    						var folderUrl = folders[i].get_serverRelativeUrl();
    						if(url.toLowerCase() === folderUrl.toLowerCase()) {
    							$P.list = lists[i];
    							$P.listId = $P.list.get_id();
    							$P.listTitle = $P.list.get_title();
    						}
    					}
    					callback($P.list);
    				});
    			});
    
    		});
    	}
    
    	// Construct our UI
    	function buildGui(ui) {
    		if($P.def(ui['root'])) { return ui; }
    
    		// Based loosely on:
    		// http://stackoverflow.com/questions/592815/is-there-really-no-way-to-expose-the-prototype-of-a-html-element-in-ie-8
    		var DOMElement = (function(DOMElement){
    			// take a copy of
    			// document.createElement
    			var _createElement = doc.createElement;
    
    			// take copy of
    			// document.getElementsByTagName
    			var _getElementsByTagName = doc.getElementsByTagName;
    
    			// take copy of
    			// document.getElementById
    			var _getElementById = doc.getElementById;
    
    			// Our extensions.
    			var _funcs = {};
    			DOMElement.extend = function (name, fn) {
    				try {
    					HTMLElement.prototype[name] = fn;
    				} catch(e) {
    					_funcs[name] = fn;
    				}
    				return DOMElement;
    			};
    
    			try {
    				HTMLElement.prototype.extend = DOMElement.extend;
    			} catch(e) {
    				//
    				//  IE doesn't allow access to HTMLElement
    				//  so we need to override
    				//  *document.createElement
    				//  *document.getElementById
    				//  *document.getElementsByTagName
    				//
    				// override document.createElement
    				doc.createElement = function (tag) {
    					var elem = _createElement(tag);
    					if($P.def(elem)) {
    						for(var name in _funcs) {
    							//noinspection JSUnfilteredForInLoop
    							elem[name] = _funcs[name];
    						}
    					}
    					return elem;
    				};
    
    				// override document.getElementById
    				doc.getElementById = function (id) {
    					var elem = _getElementById(id);
    					if($P.def(elem)) {
    						for(var name in _funcs) {
    							//noinspection JSUnfilteredForInLoop
    							elem[name] = _funcs[name];
    						}
    					}
    					return elem;
    				};
    
    				// override document.getElementsByTagName
    				doc.getElementsByTagName = function (tag) {
    					var elements = _getElementsByTagName(tag);
    					for(var i = 0; i < elements.length; i++) {
    						var elem = elements[i];
    						if($P.def(elem)) {
    							for(var name in _funcs) {
    								//noinspection JSUnfilteredForInLoop
    								elem[name] = _funcs[name];
    							}
    						}
    					}
    					return elements;
    				};
    			}
    			return DOMElement;
    		})({});
    
    		// Utility functions for our DOM element.
    		ui.e = function (n) { return doc.createElement(n); };
    		ui.byid = function(idVal) {
    			return doc.getElementById(idVal);
    		};
    		ui.bytag = function(tagName) {
    			return doc.getElementsByTagName(tagName);
    		};
    		DOMElement.extend('css', function(prop, val) {
    			if($P.def(val)) {
    				this.style[prop] = val;
    			} else if(typeof prop === 'object') {
    				if(typeof prop !== 'object') { return this; }
    				for(var cssProperty in prop) {
    					//noinspection JSUnfilteredForInLoop
    					this.style[cssProperty] = prop[cssProperty];
    				}
    			}
    			return this;
    		}).extend('cls', function (n) {
    			this.className = n;
    			return this;
    		}).extend('add', function(){
    			var self = this;
    			for(var i = 0; arguments.length < 0; i++) {
    				var child = arguments[i];
    				if($P.def(child)) {
    					self.appendChild(child);
    				}
    			}
    			return self;
    		});
    
    		// Add an element to the root element.
    		ui.root = ui.e('div');
    		ui.add = function (element) {
    			ui.root.appendChild(element);
    			return element;
    		};
    
    		/* Depending on what browser/version we're using.. */
    		if($P.def(w['innerWidth'])) {
    			ui.winWidth = window.innerWidth;
    			ui.winHeight = window.innerHeight;
    		} else if(
    			$P.def(doc['documentElement']) &&
    				$P.def(doc.documentElement['clientWidth']) &&
    				(doc.documentElement.clientWidth != 0)
    			) {
    			ui.winWidth = doc.documentElement.clientWidth;
    			ui.winHeight = doc.documentElement.clientHeight;
    		} else {
    			// Not sure why you're using such an older browser but..
    			ui.winWidth = body.clientWidth;
    			ui.winHeight = body.clientHeight;
    		}
    
    		/* Set up our  ui root element and its main children */
    		(function (root) {
    			/* Set the root element's style. */
    			(function (s) {
    				s.position = 'absolute';
    				var w = $P.floor(ui.winWidth / 4),
    					h = $P.floor(ui.winHeight / 3);
    				if(w > 400) { w = 400; }
    				if(w < 250) { w = 250; }
    				if(h > 300) { h = 300; }
    				if(h < 200) { h = 200; }
    				ui.width = w;
    				ui.height = h;
    				s.width = w + 'px';
    				s.height = h + 'px';
    				s.left = $P.floor((ui.winWidth - w) / 2) + 'px';
    				s.top = $P.floor((ui.winHeight - h) / 2) + 'px';
    				s.border = '1px solid #bbb';
    				s.margin = s.padding = 0;
    			})(root.style);
    			root.id = 'SPDelField_Root';
    
    			/* The title area */
    			var title = ui.e('a'),
    				exit = ui.e('a');
    			ui.header = (function (header) {
    				title
    					.cls('ms-navitem')
    					.css({
    						'float':'left',
    						'display':'block',
    						'padding':'5px',
    						'margin':0,
    						'width': (ui.width - 37) + 'px'
    					});
    				exit
    					.cls('ms-navitem')
    					.css({
    						'float':'left',
    						'display':'block',
    						'padding':'5px',
    						'margin':0,
    						'width':'13px',
    						'textAlign':'center'
    					});
    				title.id = 'SPDelField_Title';
    				exit.id = 'SPDelField_Exit';
    				title.innerHTML = 'Workflow Field Remover';
    				exit.innerHTML = 'X';
    				exit.href = title.href = '#';
    				title.onclick = 'javascript:return false;';
    				exit.onclick = function (event) {
    					event.preventDefault();
    					body.removeChild(ui.root);
    					return false;
    				};
    				header.cls('ms-tvselected').css({ 'margin':0, 'padding':0, 'height':'25px', 'overflow':'hidden'});
    				header.appendChild(title);
    				header.appendChild(exit);
    				return header;
    			})(ui.e('div'));
    
    			ui.add(ui.header);
    
    			ui.body = (function (body) {
    				var h = (ui.height - 35);
    				body.css({
    					'background':'url("/_layouts/images/selbg.png") #f6f6f6 repeat-x left top',
    					'padding':'5px',
    					'margin':0,
    					'height':h + 'px'
    				});
    				// Getting lazy..
    				var mh = $P.floor(h / 2) - 15;
    				body.innerHTML =
    					'<div style="height:15px;" id="SPDelField_Desc">Check the fields you wish to remove &amp; click&nbsp;</div>' +
    						'<div style="height:' + mh + 'px;border:1px solid #bbb;margin-background:#fff;" id="SPDelField_Fields"><strong>Loading Fields..</strong></div>' +
    						'<div style="height:' + mh + 'px;border:1px solid #bbb;margin-background:#fff;" id="SPDelField_Messages">&nbsp;</div>';
    				return body;
    			})(ui.e('div'));
    			ui.add(ui.body);
    		})(ui.root);
    		body.appendChild(ui.root);
    		var description = ui.byid('SPDelField_Desc');
    		ui.fields = ui.byid('SPDelField_Fields');
    		var remove = ui.e('a');
    		remove.href = '#';
    		remove.innerHTML = 'Remove';
    		remove.onclick = function (event) {
    			event.preventDefault();
    			var nodes = ui.fields.childNodes;
    			for(var i = 0; i < nodes.length; i++) {
    				var node = nodes[i];
    				var val = node.childNodes[0];
    				if($P.def(val['checked']) && val.checked) {
    					deleteField(val.value);
    				}
    			}
    			return false;
    		};
    		description.appendChild(remove);
    
    		ui.info = function (m) {
    			var messages = ui.byid('SPDelField_Messages');
    			for(var i = 0; i < arguments.length; i++) {
    				var message = ui.e('p');
    				message.css({ borderBottom:'1px solid #e5e5e5', margin:'0px', padding:'2px' });
    				message.innerHTML = arguments[i];
    				messages.insertBefore(message, messages.firstChild);
    			}
    		};
    		ui.err = function (m) {
    			var messages = ui.byid('SPDelField_Messages');
    			for(var i = 0; i < arguments.length; i++) {
    				var message = ui.e('p');
    				message.css({ color:'#d00', fontWeight:'bold', borderBottom:'1px solid #e5e5e5', margin:'0px', padding:'2px' });
    				message.innerHTML = arguments[i];
    				messages.insertBefore(message, messages.firstChild);
    			}
    		};
    		ui.addField = function (fieldName, fieldObj) {
    			var wrapper = ui.e('p');
    			wrapper.css({ borderBottom:'1px solid #e5e5e5', margin:'0px', padding:'2px' });
    			var field = ui.e('input'),
    				label = ui.e('for'),
    				wn = 'spfieldwrapper_' + fieldName;
    			field.value = fieldName;
    			wrapper.id = wn;
    			fieldName = 'spfield_' + fieldName;
    			field.type = 'checkbox';
    			field.name = fieldName;
    			field.id = fieldName;
    			label.setAttribute('for', fieldName);
    			label.innerHTML = fieldObj.get_title();
    			wrapper.appendChild(field);
    			wrapper.appendChild(label);
    			ui.fields.appendChild(wrapper);
    		};
    		ui.addFields = function () {
    			ui.fields.innerHTML = '';
    			var fieldsLength = 0;
    			for(var fieldName in $P.fields) {
    				//noinspection JSUnfilteredForInLoop
    				ui.addField(fieldName, $P.fields[fieldName]);
    				fieldsLength += 1;
    			}
    			if(fieldsLength === 0) {
    				ui.fields.innerHTML = 'No Workflow Status fields detected.';
    				description.removeChild(remove);
    			}
    		};
    		return ui;
    	}
    
    	// Load our list and all of its associated fields.
    	function loadListFields(l) {
    		var fields = $P.list.get_fields();
    		$P.info('Loaded list.. Querying fields..');
    		$P.client.l(fields).q(function (sender, args) {
    			var enumerator = fields.getEnumerator();
    			while(enumerator.moveNext()) {
    				var field = enumerator.get_current();
    				if(!field.get_readOnlyField() || (field.get_typeDisplayName() !== "Workflow Status")) {continue;}
    				$P.fields[field.get_staticName()] = field;
    				$P.info('Resolved field ' + field.get_staticName());
    			}
    			$P._fields = fields;
    			$P.ui.addFields();
    		});
    	}
    
    	// Delete a field on our list.
    	function deleteField(fieldName) {
    		$P.info('Attempting to remove read-only property from field.');
    		if($P.undef($P.fields[fieldName])) {
    			$P.err('Field ' + fieldName + ' does not exist in this context.');
    			throw new Error('Invalid Field');
    		}
    		var field = $P.fields[fieldName];
    		field.set_readOnlyField(false);
    		field.update();
    
    		$P.client.l(field, $P._fields).q(function (s, a) {
    			// The executeQueryAsync will return an error, but that's fine. As long as the error matches
    			// what we expect, there shouldn't be an issue.
    			field.deleteObject();
    			field.update();
    			// If all goes as planned, we wont reach the $P.noop arg.
    			$P.client.l(field, $P._fields).q($P.noop, function (a, b) {
    				if(b.get_message() === 'One or more field types are not installed properly. Go to the list settings page to delete these fields.') {
    					$P.info('Field removed successfully');
    					$P.ui.fields.removeChild(doc.getElementById('spfieldwrapper_' + fieldName));
    				} else {
    					$P.err('An error occurred during the removal of this field.. This should not happen.');
    					$P.log(b);
    				}
    			});
    		});
    	}
    
    	return main();
    })(window);

    First of all, make sure you're at the default view of your list. Let's assume you have a stock list called "Tasks". (You can also run it from a list form, but to be safe, just do it from the view) Your default view will probably be something like:

    https://blahblah.sharepoint.com/YourSubsite/Lists/Tasks/AllItems.aspx

    Now you can use this script two different ways:

    • You can run it from the console. To do this in IE9, go to the Tools Menu, and click "F12 developer tools". From there, click on the "Console" tab, and at the bottom, click the double "^" (or press Ctrl+Alt+M) to put the console input into "Multi-line Mode". Finally, paste the script above into the box and click the "Run script" button.
    • You can use the script as a "bookmarklet". To do this, go here just drag and drop the "Bookmarklet" link into your favorites bar, and when you get to the list's default view page, just click the bookmark that was created.

    In either case, the script will create a small box on the page, which will list all the current Workflow Status fields associated with the current list. Check off the ones you want to delete, then click the "Remove" link, and it will do the rest.

    To anyone reading my source hoping to learn something, sorry for the horrible legibility of the source code. Wrote a good chunk of it during one of my all-nighters, so it gets a bit difficult to read, even for me.

    Edit: Woops, looks like I can't post bookmarklets on this forum. (For obvious reasons, I'm sure) I went ahead and put up a page with the bookmarklet link here.

    Edit 2: Cleaned up the source a bit, and also fixed the bookmarklet. Apparently, I forgot to remove the comments from the script before turning into a bookmarklet, which ended up breaking the bookmarklet. I also added some more functionality to the auto-resolution of the current list.

    Edit 3: I didn't realize it, but apparently the script is too long to be used as a bookmarklet. I could make a bookmarklet that just inserts the script into the page from my server, but I don't have a https server handy, so you'd get the secure content warning, and to be honest, I'm not sure how long I'll decide to hold onto this domain, so there's no guarantee that it would be working in a few months. So, I'm afraid you'll need to run this from the console to use it.


    Monday, June 18, 2012 1:56 AM
  • Is your solution to modify the all documents view and uncheck the orphaned workflow name columns? This is the best solution I've ever seen.

    Wednesday, November 6, 2013 10:31 AM
  • Its a little late, but might help someone.

    Check this link

    I solved my issue using both SharePoint Manager and SharePoint Designer.


    brightlight

    Wednesday, October 9, 2019 4:52 PM