更改PowerPivot文件中的连接数据

所以我遇到了一个有趣的问题。 我需要在PowerPivot查询中指定一个自定义的WHERE子句。 我必须根据外部条件来改变它。 我想编辑文件并保存副本。 任何想法如何做到这一点? 我从二进制打开PowerPivot文件,但它似乎encryption…

你可以去现有的连接,然后在那里进行更新。 如果您再次打开相同的数据源(SQL,SSRS或其他任何东西),而不是更改现有连接上的参数,则PowerPivot会将这些参数视为单独的连接,从而导致性能下降。

解决方法是以Zipforms打开Excel工作簿(使用Package类)。

如果你想修改查询,你可以。 /xl/customData/item1.data中的文件是一个备份文件,表示用于处理查询的PowerPivot数据库(它只是在Vertipaq模式下运行的Analysis Services数据库)。 您需要将文件恢复到以Vertipaq模式运行的SSAS实例。 完成之后,将查询编写为ALTER脚本。 修改脚本(在这种情况下,用我的实际项目IDreplace@projectId),然后在数据库上运行它们。 完成这一切后,将数据库备份回Excel工作簿。 这修改了查询。

连接数据存储在/xl/connections.xml文件中。 打开,修改和replace。 重新整理一遍,现在你又有了一本工作簿。

这是我所做的代码。 您将不得不根据需要调用这些方法。 基本的想法在那里,虽然…

const string DBName = "Testing"; const string OriginalBackupPath = @"\\MyLocation\BKUP.abf"; const string ModifiedBackupPath = @"\\MyLocation\BKUPAfter.abf"; const string ServerPath = @"machineName\powerpivot"; private static readonly Server srv = new Server(); private static readonly Scripter scripter = new Scripter(); private static Database db; private static byte[] GetPackagePartContents(string packagePath, string partPath) { var pack = Package.Open(packagePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); var part = pack.GetPart(new Uri(partPath, UriKind.Relative)); var stream = part.GetStream(); var b = new byte[stream.Length]; stream.Read(b, 0, b.Length); stream.Flush(); stream.Close(); pack.Flush(); pack.Close(); return b; } private static void WritePackagePartContents(string packagePath, string partPath, byte[] contents) { var uri = new Uri(partPath, UriKind.Relative); var pack = Package.Open(packagePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); var part = pack.GetPart(uri); var type = part.ContentType; pack.DeletePart(uri); pack.CreatePart(uri, type); part = pack.GetPart(uri); var stream = part.GetStream(); stream.Write(contents, 0, contents.Length); stream.Flush(); stream.Close(); pack.Flush(); pack.Close(); } private static void RestoreBackup(string server, string dbName, string backupPath) { srv.Connect(server); if (srv.Databases.FindByName(dbName) != null) { srv.Databases.FindByName(dbName).Drop(); srv.Update(); } srv.Restore(backupPath, dbName, true); srv.Update(); srv.Refresh(); } private static void WriteContentsToFile(byte[] contents, string filePath) { var fileStream = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write); fileStream.Write(contents, 0, contents.Length); fileStream.Flush(); fileStream.Close(); } private static byte[] ReadContentsFromFile(string filePath) { var fileStream = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write); var b = new byte[fileStream.Length]; fileStream.Read(b, 0, b.Length); fileStream.Flush(); fileStream.Close(); return b; } private static XDocument GetAlterScript(MajorObject obj) { var stream = new MemoryStream(); var streamWriter = XmlWriter.Create(stream); scripter.ScriptAlter(new[] { obj }, streamWriter, false); streamWriter.Flush(); streamWriter.Close(); stream.Flush(); stream.Position = 0; var b = new byte[stream.Length]; stream.Read(b, 0, b.Length); var alterString = new string(Encoding.UTF8.GetString(b).ToCharArray().Where(w => w != 65279).ToArray()); var alter = XDocument.Parse(alterString); stream.Close(); return alter; } private static void ExecuteScript(string script) { srv.Execute(script); srv.Update(); db.Process(); db.Refresh(); } private static void ProcessPowerpointQueries(string bookUrl, string projectId) { byte[] b = GetPackagePartContents(bookUrl, "/xl/customData/item1.data"); WriteContentsToFile(b, OriginalBackupPath); RestoreBackup(ServerPath, DBName, OriginalBackupPath); var db = srv.Databases.GetByName(DBName); var databaseView = db.DataSourceViews.FindByName("Sandbox"); var databaseViewAlter = GetAlterScript(databaseView); var cube = db.Cubes.FindByName("Sandbox"); var measureGroup = cube.MeasureGroups.FindByName("Query"); var partition = measureGroup.Partitions.FindByName("Query"); var partitionAlter = GetAlterScript(partition); var regex = new Regex(@"\s@projectid=\w*[ ,]"); var newDatabaseViewAlter = databaseViewAlter.ToString().Replace(regex.Match(databaseViewAlter.ToString()).Value.Trim(',',' '), @"@projectid=" + projectId); ExecuteScript(newDatabaseViewAlter); var newPartitionAlter = partitionAlter.ToString().Replace(regex.Match(partitionAlter.ToString()).Value.Trim(',', ' '), @"@projectid=" + projectId); ExecuteScript(newPartitionAlter); db.Backup(ModifiedBackupPath, true); WritePackagePartContents(bookUrl, @"/xl/customData/item1.data", ReadContentsFromFile(ModifiedBackupPath)); db.Drop(); srv.Disconnect(); } private static void ProcessWorkbookLinks(string bookUrl, string newCoreUrl) { var connectionsFile = GetPackagePartContents(bookUrl, @"/xl/connections.xml"); var connectionsXml = Encoding.UTF8.GetString(connectionsFile); connectionsXml = connectionsXml.Replace( new Regex(@"Data Source=\S*;").Match(connectionsXml).Value.Trim(';'), @"Data Source=" + newCoreUrl); WritePackagePartContents(bookUrl, @"/xl/connections.xml", connectionsXml.Replace(@"https://server/site/", newCoreUrl).ToCharArray().Select(Convert.ToByte).ToArray()); }