所以我遇到了一个有趣的问题。我需要在 PowerPivot 查询中指定自定义 WHERE 子句。我必须根据外部条件来改变它。我想编辑文件并保存一份副本。知道怎么做吗?我从二进制文件中打开了 PowerPivot 文件,但它似乎是加密的...
问问题
6622 次
2 回答
1
您可以转到现有连接,然后在那里进行更新。如果您再次打开相同的数据源(SQL、SSRS 或其他任何东西)而不是更改现有连接上的参数,则会减慢您的性能,因为 PowerPivot 会将它们视为单独的连接。
于 2011-07-15T21:57:07.463 回答
0
解决方案是将 Excel 工作簿作为 Zip 打开(使用 Package 类)。
如果您要修改查询,则可以。/xl/customData/item1.data 中的文件是一个备份文件,它代表用于处理查询的 PowerPivot 数据库(它只是一个在 Vertipaq 模式下运行的 Analysis Services 数据库)。您需要将文件恢复到以Vertipaq 模式运行的 SSAS 实例。完成后,将查询编写为 ALTER 脚本。修改脚本(在本例中,将 @projectId 替换为我的实际 projectID),然后针对数据库运行它们。完成所有这些后,备份数据库并放回 Excel 工作簿。这会修改查询。
连接数据存储在 /xl/connections.xml 文件中。打开它,修改和替换。再次重新打包,现在您又拥有了一个工作簿。
这是我制作的代码。您必须根据需要调用这些方法。基本的想法是存在的,虽然......
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());
}
于 2011-11-04T19:18:29.660 回答