Wednesday, December 22, 2010

Building a Search Center

To build a Search Center create a new site, selecting Enterprise > Search Center with Tabs.

Once the site is built, configure the following items:
  1. Search scopes
  2. Search pages
  3. Search tabs
  4. Results pages
  5. Assign scopes to result pages
  6. Results tabs
  7. Advanced Search Pages
Create a Search Scope

Scopes can be created either at the Site Collection level using SharePoint Central Administrator or at the Site Collection thru Site Actions > Site Settings > Search Scopes.

If you need to narrow a scope down to folder level, then use the Site Actions > Site Settings approach. If your scopes are broader and can be handled with Content Sources and Metadata Properties then use the SharePoint Central Administration approach.

Create a New Search Page
  1. From the Search Center
  2. Site Actions
  3. Create Page
  4. Enter a Title, Description and change the URL if desired
  5. Select (Welcome Page) Search Page
  6. Click Create
Create a New Search Tab
  1. Edit the new search page just created
  2. Click Add New Tab
  3. Enter a name for the tab
  4. Specify the name for the search page just created (ex. MySearchPage.aspx)
  5. Enter a tooltip
  6. Click OK
Create a New Results Page

Search pages and tabs work in pairs, for every search page, there must be a matching results page and for every search tab, there must be a matching results tab. A unique results page allows the assignment of unique scopes to a search.
  1. From the Search Center
  2. Site Actions
  3. Create Page
  4. Enter a Title, Description and change the URL if desired
  5. Select (Welcome Page) Search Page Results
  6. Click Create
  7. Edit the new page
  8. On the Search Box > Modify Shared Web Part
  9. Expand Miscellaneous
  10. Enter the name of the new search page created above in 'Target search results page URL"
  11. Note you will come back after creating the Advanced Search page, to enter it's URL in the "Advanced Search page URL"
  12. Click Apply
Assign Scopes to Result Page
  1. Continue editing the new results page
  2. On the Search Core Results web part > Modify Shared Web Part
  3. Expand Miscellaneous
  4. Enter the name of the Search Scope created above.
  5. Click Apply
Create a New Results Tab
  1. Still editing the new results page just created
  2. Click Add New Tab
  3. Enter a name for the tab
  4. Specify the name for the search page just created (ex. MySearchPageResults.aspx)
  5. Enter a tooltip
  6. Click OK
Create an Advanced Search Page
  1. Navigate back to the initial Search Center so you are not looking at a results page
  2. Site Actions > Create Page
  3. Enter a Title, Description and change the URL if desired
  4. Select (Welcome Page) Advanced Search
  5. Click Create
  6. Click Add a Web Part
  7. Check 'Advanced Search Box'
  8. Click Add
  9. On the 'Advanced Search Box' > Modify Shared Web Part
  10. Expand Scopes
  11. Check 'Show the scope picker'
  12. Change the 'Display Group' to the correct one
  13. Click OK
  14. Edit the New Results Page previously created
  15. On the Search Box > Modify Shared Web Part
  16. Expand Miscellaneous
  17. Enter the name of the advanced search page created in 'Advanced Search page URL". Be sure to include the entire path.
  18. Click Apply
  19. Edit the New Search Page previously created
  20. On the Search Box > Modify Shared Web Part
  21. Expand Miscellaneous
  22. Enter the name of the advanced search page created in 'Advanced Search page URL". Be sure to include the entire path.
  23. Click Apply
Be sure the check-in and publish all new and edited pages.

Monday, November 22, 2010

SQL Server 2008 Releases

What is available:
  • SQL Server 2008 SP1 CU 11
  • SQL Server 2008 SP2 CU 1
  • SQL Server 2008 R2 SP CU2

Friday, November 12, 2010

Successfully Finished - but OK Button Disabled

Recently had an issue when processing dimensions in BPC. The process would complete without errors, but the OK button was disabled. The only way to exit was killing the application. Turns out the recycle limit on the DefaultAppPool was causing this.

Even though minimum memory was set to 60% before the app pool would recycle, and even though the memory on the server never got close to 60%, the process wouldn't finish. I turned off recycling based on memory usage and processing completed fine.

Wednesday, October 6, 2010

32 bit ODBC DSN on a 64 bit machine

To create a 32 bit ODBC DSN run C:\Windows\SysWow64\odbcad32.exe

Wednesday, August 18, 2010

Hiding Edit in Datasheet, Export to Spreadsheet and Open with Access Menu Items

To hide the Edit in Datasheet, Export to Spreadsheet and Open with Access menu items. Create a custom Permission Level using the directions found here.

When specifying the permissions for the custom Permission Level make sure Use Client Integration Features is unchecked, this will prevent users from launching client applications which includes Access embedded in the datasheet, as well as the external applications. Unchecking Use Remote Interfaces is probably a safe bet as well.

Creating Custom Permission Levels

Frustrated by the limit of existing Permission Levels within SharePoint (Full Control, Design, Approve, Contribute, Read, etc.) I finally discovered how to create my own. These are created at the Site level like this:
  1. Site Actions > Site Settings > Advanced Permissions
  2. Settings > Permission Levels
  3. Add a Permission Level
  4. Enter a Name and a Description
  5. Select permissions from the beautiful buffet of security settings are available
  6. Click Create
At this point the new Permission Level is available when assigning permissions to a user or group!

Thursday, July 29, 2010

The Perfect SharePoint Document Template

SharePoint is a good Document Management System until you need to embed properties within a document. Once properties are embedded they won't update until you print, you manually update the fields or you add a macro to update them every time the document is opened.

SharePoint as a Document Management System also falls down when you want to update the template used by documents and have that update affect all existing documents.

The Perfect Document Template

The perfect template will have a macro that updates embedded SharePoint properties whenever a document is opened. And the template will allow me to change the header and footer for all the documents whenever I want. To do this, I need a template that I can swap out whenever I want.

Because of the default behaviour of SharePoint and Word, the template is downloaded once when you open a document. The template is never pulled again from SharePoint. See this reference. This means any updates you make to the template do not pass down to you.

The article refered to from Microsoft above discusses building an XML Expansion Pack, which is overkill for what I need. And in fact doesn't work with MOSS only WSS.

The simpler solution is to build 2 templates: a driver template and an actual template.

The Driver Template

This is the template that is bound to the Content Type and is the one that gets downloaded and never updated. What this template does is binds the actual template you want to associate with the actual document.

The Actual Template

This template contains code to dynamically build the header and footer and update all the embedded properties.

To Build This Solution
  1. Define your Document Library
  2. Define your Content Type
  3. Create a Driver Template in the Forms directory of your Document Library
  4. Create an Actual Template in the Forms directory as well
  5. Bind the Driver Template to the Content Type
  6. Test
I won't bother showing you how to create a Document Library or defining a Content Type, but I will show you steps 3 and 4.

Create a Driver Template

Open MS Word.
Alt + F8 will take you to macros
Create a macro called UpdateTemplate
Once you are in Visual Basic, paste this code in the code window:

Private Sub Document_New()

'temporarily unlink this file from the template
ActiveDocument.AttachedTemplate = ""

'and update
UpdateTemplate

End Sub

Sub UpdateTemplate()

Dim strTemplatePath As String
Dim doc As Document

' Get the path of the template file.
strTemplatePath = "http://sharepoint-test/Docs/MyLibrary/Forms/ActualTemplate.dotm"

' Open the document template and save it to the local machine
Set doc = Application.Documents.Open(strTemplatePath, Visible:=False)
doc.SaveAs Environ("Temp") & "\ActualTemplate.dotm"
doc.Close

' Add the template as an Add-in
Application.AddIns.Add Environ("Temp") & "\ActualTemplate.dotm"

' Run the macro in the ActualTemplate template
Application.Run "UpdateThisDocument"

' Rest of the lines do not execute.
Application.AddIns.Unload True
On Error Resume Next 'In case another document is using the template
Kill Environ("Temp") & "\ActualTemplate.dotm"

ActiveDocument.AttachedTemplate = strTemplatePath

End Sub

Private Sub Document_Open()

'do not do anything in the case where the solution author opens the template directly
If (InStr(1, ActiveDocument.FullName, ".dotm", vbTextCompare) = 0) Then

'temporarily unlink this file from the template
ActiveDocument.AttachedTemplate = ""

'update template
UpdateTemplate

End If

End Sub

Close the VB environment and save your template.

NOTE: Make sure to save it as a .dotm (macro enabled template)

Create an Actual Template

Open MS Word.
Alt + F8 will take you to macros
Create a macro called UpdateThisDocument
Once you are in Visual Basic, paste this code in the code window:


Sub Document_New()

End Sub

Sub Document_Open()

UpdateThisDocument

End Sub

Public Sub UpdateThisDocument()

Application.ScreenUpdating = False

Margins

'Header
ClearHeaders
AddHeader

'Footer
ClearFooters
AddFooter

'Update Fields
UpdateFields

'Display Document Normally
If ActiveDocument.ActiveWindow.View.SplitSpecial = wdPaneNone Then
ActiveDocument.ActiveWindow.ActivePane.View.Type = wdPrintView
ActiveDocument.ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
ActiveDocument.ActiveWindow.ActivePane.View.Type = wdPrintView
Else
ActiveDocument.ActiveWindow.View.Type = wdPrintView
ActiveDocument.ActiveWindow.View.SeekView = wdSeekMainDocument
ActiveDocument.ActiveWindow.View.Type = wdPrintView
End If

End Sub

Private Sub Margins()

With ActiveDocument.Styles(wdStyleNormal).Font
If .NameFarEast = .NameAscii Then
.NameAscii = ""
End If
.NameFarEast = ""
End With
With ActiveDocument.PageSetup
.LineNumbering.Active = False
.TopMargin = InchesToPoints(0.5)
.BottomMargin = InchesToPoints(0.7)
.LeftMargin = InchesToPoints(0.5)
.RightMargin = InchesToPoints(0.5)
.Gutter = InchesToPoints(0)
.HeaderDistance = InchesToPoints(0.4)
.FooterDistance = InchesToPoints(0.5)
.PageWidth = InchesToPoints(8.5)
.PageHeight = InchesToPoints(11)
.SectionStart = wdSectionNewPage
.OddAndEvenPagesHeaderFooter = False
.DifferentFirstPageHeaderFooter = False
.VerticalAlignment = wdAlignVerticalTop
.SuppressEndnotes = False
.MirrorMargins = False
.TwoPagesOnOne = False
.BookFoldPrinting = False
.BookFoldRevPrinting = False
.BookFoldPrintingSheets = 1
.GutterPos = wdGutterPosLeft
End With

End Sub

Private Sub ClearHeaders()
Dim hdr As HeaderFooter

For Each hdr In ActiveDocument.Sections(1).Headers
hdr.Range.Text = vbNullString
Next hdr

End Sub

Private Sub AddHeader()

'
'TODO: Add your header code here
'

End Sub

Private Sub ClearFooters()
Dim hdr As HeaderFooter

For Each hdr In ActiveDocument.Sections(1).Footers
hdr.Range.Text = vbNullString
Next hdr

End Sub

Private Sub AddFooter()

'
'TODO: Add your footer code here
'

End Sub

Private Sub UpdateFields()

With Options
.UpdateFieldsAtPrint = True
.UpdateLinksAtPrint = True
End With

If ActiveDocument.ActiveWindow.View.SplitSpecial <> wdPaneNone Then
ActiveDocument.ActiveWindow.Panes(2).Close
End If

ActiveDocument.ActiveWindow.View = wdNormalView

'Application.ScreenUpdating = False

If ActiveDocument.ActiveWindow.ActivePane.View.Type = wdNormalView Or ActiveDocument.ActiveWindow.ActivePane.View.Type = wdOutlineView Then
ActiveDocument.ActiveWindow.ActivePane.View.Type = wdPrintView
End If

'Footer
ActiveDocument.ActiveWindow.ActivePane.View.SeekView = wdSeekPrimaryFooter
Selection.WholeStory
Selection.Fields.Update

'Main Document
ActiveDocument.ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
Selection.WholeStory
Selection.Fields.Update

'Header
ActiveDocument.ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.WholeStory
Selection.Fields.Update

End Sub

Close the VB environment and again save your template as a .dotm file.

Bind the Driver Template to the Content Type

Go to your Document Library
Settings > Document Library Settings
Under Content Types, click on your Content Type
Click Advanced Settings
Enter the URL for the DriverTemplate.dotm (http://sharepoint-test/Docs/MyLibrary/Forms/DriverTemplate.dotm)
Click OK

Test

In the Document Library, click New and select your Content Type.
At this point your macro code in ActualTemplate.dotm should have fired. Any header or footer creation should have occurred.


Friday, April 2, 2010

Loading BPC Data the Old Fashioned Way; Using SQL

Thanks to Gert Andries van den Berg on the SAP BPC forums for making sense of all this. In a nutshell, by writing records to either the WB or FAC2 table, the cube is updated. No need to build SSIS package with Dumpload task. This can be done with SQL. Writing to the FAC2 table seems to be the destination of choice. Though I've yet to determine if running optimization is required to see data in reports.

From Gert Andries van den Berg.
As per the tuning doc:

WB – real time data input (ROLAP partition)
This is data that is the most current data sent to the system. Data sent by BPC for Excel data sends and Investigator browser data sends is placed in real-time storage.
FAC2 – short term and Data Manager imports (MOLAP partition)
This is data that is not real-time data, but is also not in long-term storage yet. When you load data via Data Manager (automatic data load from external data sources), it loads the data to short-term storage so that the loaded data does not affect system performance. Only the cube partition associated with this table is processed, so the system is not taken offline.
Fact – long term history (MOLAP partition)
This is the main data storage. All data eventually resides in long-term storage. Data that is not accessed very often remains in long-term storage so that the system maintains performance
This structure allows SAP BPC to maintain the same performance over time even when there is a large increase in data volumes.
Periodically clearing real-time data greatly optimizes the performance of the system and an “Optimization” process is required (this could be scheduled automatically based on given parameters like a numbers of records threshold).

Lite Optimization:

Clears Real-time data storage (WRITEBACK) and moves it to short-term data storage (FAC2). This option doesn’t take the system offline, and can be scheduled during normal business activity.

Incremental Optimization:

Clears both real-time and Short-term data storage (WB and FAC2) and moves both to Long-term data storage (FACT).

This option should be run when the system is offline, but it will not take the system offline so it should be run during off-peak periods of activity.

Full Process Optimization:

Clears both real-time and short-term data storage and processes the dimensions.

This option takes the system offline and takes longer to run than the incremental optimization.

It is best run scheduled at down-time periods – for example after a month-end close.
The Compress Database option is available to rationalize the Fact Tables. “Compress” sums multiple entries for the same CurrentView into one entry so that data storage space is minimized. Compressed databases also process more quickly.


More info on this topic from Sorin Radulescu:
First you have to be aware about structure of BPC cubes:
Each cube has 3 partitions:
1. fact - MOLAP
2. fac2 - MOLAP
3. WB - ROLAP

When you insert records into WB table because WB is ROLAP partitions you will see the impact of that insert into cube in Real Time.
If you insert records into any of MOLAP partitions without processin the partition you are not able to see these records into cube.
I think now you have a clear picture about BPC cube and you undertsood diference between MOLAP and ROLAP partitions.

Lite Optimize is necessary just to keep under contrl the number of records from WB table.
For SSAS if a Rolap Partitions has more than 100 000 records retrieve data from that cube it will be very slow if in the same time users are doing insert into WB Table.
So Lite optimize is schedule usually every 15 minutes when number of records is over 20 000.
That's means every 15 minutes this dtsx package check if WB has 20 000 records.
If yes then is running this process
If not then is not doing anything.

LITE Optimize process
It is doing the follow steps:
1. Copy records from wb to fac2 and marlk the records from wb move into fac2
2. Create a temporary partitions and start to process this partition just for these records move from wb table
3. When it is finishing the process of partition then the system is doing in transaction the follow:
- merge partition fac2 with temp partition
- delete the records marked from wb

Tuesday, February 16, 2010

Fixing a Troublesome Network Connection

netsh winsock reset
netsh int ip reset C:\Log.txt
reboot

Friday, January 15, 2010

BPC SSIS Tasks

In order for BPC SSIS Tasks to be available for use in SSIS Packages, the OSoft Task dll files must be placed in Drive:\Program Files\Microsoft SQL Server\100\DTS\Tasks\ for SQL 2008.

Tuesday, January 12, 2010

appSettings for a SharePoint Timer Job

The SPTimerJobs run under OWSTIMER.exe which doesn't use web.config or it seems machine.config. So add an OWSTIMER.EXE.config file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN. This is the format of the file:













Failure adding assembly to the cache: Cannot create a file when that file already exists

So trying to add a Timer Job to the GAC causes:

"Failure adding assembly to the cache: Cannot create a file when that file already exists"

How do you get around it? well, try these things

1. if you have any dos windows/windows explorer windows in the assembly folder (or deeper) then move out of those folders (or close the windows down)

2. if you have Visual Studio open, and your project has a reference to your assembly, then you will need to close this down. Give it a while tho, even once your VS 200x has disappeared it is still unloading in the back ground

3. GacUtil /cdl - clears the assembly cache

4. do a IIS reset, if you have used the assembly in any web applications

5. reboot :'(

Thanks to Victor