SELECT
	P.[Object Type],
	P.[Permission State],
	P.Permission,
	P.[Object Schema],
	P.[Object Name],
	P.[Column Name],
	P.Grantee,
	P.[Permission Script]
FROM
	(
		SELECT
			CASE
				WHEN P.class IN (0, 3) /* database, schema */ THEN P.class_desc
				ELSE O.type_desc
			END AS [Object Type],
			CASE
				WHEN P.class IN (0, 3) /* database, schema */ THEN ''
				ELSE SCHEMA_NAME(O.schema_id)
			END AS [Object Schema],
			CASE
				WHEN P.class = 3 /* schema */ THEN SCHEMA_NAME(P.major_id)
				WHEN P.class = 1 /* object or column */ THEN OBJECT_NAME(P.major_id)
				ELSE ''
			END AS [Object Name],
			ISNULL(C.name, '') AS [Column Name],
			USER_NAME(P.grantee_principal_id) AS [Grantee],
			P.permission_name AS [Permission],
			P.state_desc AS [Permission State],
			CASE P.state
				WHEN 'W' THEN 'GRANT'
				ELSE P.state_desc
			END + ' ' +
				CASE
					WHEN P.class = 0 /* database */ THEN P.permission_name + ' TO ' + QUOTENAME(USER_NAME(P.grantee_principal_id)) COLLATE database_default
					WHEN P.class = 3 /* schema */ THEN P.permission_name + ' ON SCHEMA::' + QUOTENAME(SCHEMA_NAME(P.major_id)) + ' TO ' + QUOTENAME(USER_NAME(P.grantee_principal_id))
					WHEN P.minor_id <> 0 /* column */ THEN P.permission_name + ' ON ' + QUOTENAME(SCHEMA_NAME(O.schema_id)) + '.' + QUOTENAME(O.name) + ' (' + QUOTENAME(C.name) + ') TO ' + QUOTENAME(USER_NAME(P.grantee_principal_id))
					ELSE P.permission_name + ' ON ' + QUOTENAME(SCHEMA_NAME(O.schema_id)) + '.' + QUOTENAME(O.name) + ' TO ' + QUOTENAME(USER_NAME(P.grantee_principal_id))
				END +
				CASE P.state
					WHEN 'W' THEN ' WITH GRANT OPTION'
					ELSE ''
				END 
				+ ';'
				AS [Permission Script]
		FROM
			sys.database_permissions P
				LEFT JOIN
					sys.all_objects O ON
						O.object_id = P.major_id
				LEFT JOIN
					sys.all_columns C ON
						C.object_id = P.major_id AND
						C.column_id = P.minor_id
		WHERE
			NOT
			(
				P.class = 1 /* object or column */ AND
				(
					EXISTS (
						SELECT * 
						FROM sys.extended_properties EP 
						WHERE 
							EP.major_id = O.object_id AND 
							EP.name = 'microsoft_database_tools_support'
						) OR
					O.is_ms_shipped = 1
				)
			)
	) P
ORDER BY
	P.Grantee,
	P.[Object Schema],
	P.[Object Type],
	P.[Object Name],
	P.[Column Name],
	P.Permission;