FILTER Question In MDX

I have an existing MDX query that I inherited that I need to modify. Here is the query:

WITH 

MEMBER [Time].[Year - Month].[YTD] AS AGGREGATE(YTD(StrToMember(@SelectedMonth, CONSTRAINED)))

--< We need to OT over the individual months in YTD >--
MEMBER [Measures].[Overtime Hours] AS 
  IIF([Time].[Year - Month].CurrentMember = StrToMember(@SelectedMonth, CONSTRAINED), 
    [Measures].[Employee Overtime Hours], 
    SUM(YTD(StrToMember(@SelectedMonth, CONSTRAINED)), [Measures].[CALCED OT]))

MEMBER [Measures].[Overtime Hours %] AS '[Measures].[Overtime Hours] / [Measures].[Available Hours minus PTO]'
	
SELECT 
  {
    [Measures].[Employee Hours],
    [Measures].[Employee Hours %],
    [Measures].[Overtime Hours],
    [Measures].[Overtime Hours %],
    [MEasures].[Available Hours]
  } ON COLUMNS,
  NON EMPTY CROSSJOIN(
    FILTER(
IIF(@SelectedDiscipline = @SelectedDepartment,
      DESCENDANTS(StrToMember(@SelectedDiscipline, CONSTRAINED), [Employee].[DISC - DEPT - EMP].[Department], AFTER),
      DESCENDANTS(StrToMember(@SelectedDepartment, CONSTRAINED), [Employee].[DISC - DEPT - EMP].[Department], AFTER)
), 
      NOT INSTR([Employee].[Department].CurrentMember.MEMBER_NAME, "Freelance")),
    [Employee].[Employee Bill Rate].[Employee Bill Rate].ALLMEMBERS,
    [Employee].[Employee Level].[Employee Level].ALLMEMBERS,
    {
                	-- PTO Utilization Category excluded
		-- PRODUCTION Utiltization Category included with detail
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[PRODUCTION]},
			[Employee Hours Time Category].[Time Category].[Time Category].ALLMEMBERS),
		-- ADMIN Utiltization Category rolled-up witout detail
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[ADMIN]},
			{[Employee Hours Time Category].[Time Category].[Admin]})
                   },
                   {StrToMember(@SelectedMonth, CONSTRAINED), [Time].[Year - Month].[YTD]}
          ) DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM [OLSON BI] 
CELL PROPERTIES 
  VALUE
,BACK_COLOR
,FORE_COLOR
,FORMATTED_VALUE
,FORMAT_STRING
,FONT_NAME
,FONT_SIZE
,FONT_FLAGS;

What I need to do is add another FILTER statement to the query. I need to filter out any employees who have a Manager Name of "Olson O-Tern". Here is how I assumed the FILTER would look:

NOT INSTR([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern"

But when I try to add this line to the existing FILTER clause I get an error stating the FILTER statement only expects two arguements.

How would I alter this query to include this additional FILTER statement without affecting the rest of the query?

Thanks in advance!!

July 10th, 2013 11:09pm

Hi

You need to create an another filter to filter out Managers with required name

FILTER ([Employee].[Manager Name].[Manager Name].Members ,

             NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")

           )

Hence your filter condition integration will be like

   NOT INSTR([Employee].[Department].CurrentMember.MEMBER_NAME, "Freelance")),

-- Place this new filter here

FILTER ([Employee].[Manager Name].[Manager Name].Members ,

             NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")

           ),
   
[Employee].[Employee Bill Rate].[Employee Bill Rate].ALLMEMBERS,
   
[Employee].[Employee Level].[Employee Level].ALLMEMBERS,

Free Windows Admin Tool Kit Click here and download it now
July 11th, 2013 4:31am

Prav:

Thanks!!

So in the case of this other query, would I do essentially the same thing to add the same additional filter?

WITH

MEMBER [Time].[Year - Month].[YTD] AS AGGREGATE(YTD(StrToMember(@SelectedMonth, CONSTRAINED)))

SET [SelectedDiscipline] AS StrToMember(@SelectedDiscipline, CONSTRAINED)
SET [SelectedDepartment] AS StrToMember(@SelectedDepartment, CONSTRAINED)

MEMBER [Employee].[Department].[Non-Freelance] AS
  AGGREGATE(
    FILTER(
      IIF(@SelectedDiscipline = @SelectedDepartment,
        DESCENDANTS([SelectedDiscipline], [Employee].[DISC - DEPT - EMP].[Department], SELF),
        DESCENDANTS([SelectedDepartment], [Employee].[DISC - DEPT - EMP].[Department], SELF)),
        NOT INSTR([Employee].[DISC - DEPT - EMP].CurrentMember.MEMBER_NAME, "Freelance")))

MEMBER [Measures].[Overtime Hours Calc] AS
  SUM(
    DESCENDANTS(
      IIF(@SelectedDiscipline = @SelectedDepartment,
        STRTOMEMBER(@SelectedDiscipline, CONSTRAINED),
        STRTOMEMBER(@SelectedDepartment, CONSTRAINED)),
      [Employee].[DISC - DEPT - EMP].[DEPARTMENT],
      AFTER),
    [Measures].[Employee Overtime Hours]) 

--< We need to OT over the individual months in YTD >--
MEMBER [Measures].[Overtime Hours] AS Measures.[CALCED OT]


MEMBER [Measures].[Overtime Hours %] AS '[Measures].[Overtime Hours] / [Measures].[Available Hours minus PTO]' 

SELECT
  {
    [Measures].[Employee Hours],
    [Measures].[Employee Hours %],
    [Measures].[Overtime Hours],
    [Measures].[Overtime Hours %],
    [Measures].[Available Hours minus PTO]
  }
ON COLUMNS,
 CROSSJOIN(FILTER([Employee].[Employee Level].AllMembers, CInt([Employee].[Employee Level].CurrentMember.MEMBER_KEY) >= 1),
 CROSSJOIN(
  {[Employee].[Department].[Non-Freelance]},
  {
  -- PTO Utilization Category excluded
  -- ADMIN Utiltization Category rolled-up witout detail
  CROSSJOIN(
   {[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[ADMIN]},
   {[Employee Hours Time Category].[Time Category].[Admin]}),
  -- PRODUCTION Utiltization Category included with detail
  CROSSJOIN(
   {[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[PRODUCTION]},
   [Employee Hours Time Category].[Time Category].[Time Category].ALLMEMBERS)
  },
  {StrToMember(@SelectedMonth, CONSTRAINED), [Time].[Year - Month].[YTD]}))
 DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM [OLSON BI]
CELL PROPERTIES
  VALUE
 ,BACK_COLOR
 ,FORE_COLOR
 ,FORMATTED_VALUE
 ,FORMAT_STRING
 ,FONT_NAME
 ,FONT_SIZE
 ,FONT_FLAGS;

Thanks again!

July 11th, 2013 6:53am

Hi

Yes, It is just similar to existing filter method. Logic is to slice the Managers Members using NOT IN condition.

Free Windows Admin Tool Kit Click here and download it now
July 11th, 2013 6:59am

I tried the following, but got an error that the syntax for the FILTER statement was incorrect:

WITH 

MEMBER [Time].[Year - Month].[YTD] AS AGGREGATE(YTD(StrToMember(@SelectedMonth, CONSTRAINED)))

SET [SelectedDiscipline] AS StrToMember(@SelectedDiscipline, CONSTRAINED)
SET [SelectedDepartment] AS StrToMember(@SelectedDepartment, CONSTRAINED)

MEMBER [Employee].[Department].[Non-Freelance] AS 
  AGGREGATE(
    FILTER(
      IIF(@SelectedDiscipline = @SelectedDepartment, 
        DESCENDANTS([SelectedDiscipline], [Employee].[DISC - DEPT - EMP].[Department], SELF), 
        DESCENDANTS([SelectedDepartment], [Employee].[DISC - DEPT - EMP].[Department], SELF)),
        NOT INSTR([Employee].[DISC - DEPT - EMP].CurrentMember.MEMBER_NAME, "Freelance")))

FILTER ([Employee].[Manager Name].[Manager Name].Members , 

             NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")

           ),
Not sure what I'm goofing up...

July 11th, 2013 7:21am

Hi

Added FILTER to your code

WITH 

MEMBER [Time].[Year - Month].[YTD] AS AGGREGATE(YTD(StrToMember(@SelectedMonth, CONSTRAINED)))

--< We need to OT over the individual months in YTD >--
MEMBER [Measures].[Overtime Hours] AS 
  IIF([Time].[Year - Month].CurrentMember = StrToMember(@SelectedMonth, CONSTRAINED), 
    [Measures].[Employee Overtime Hours], 
    SUM(YTD(StrToMember(@SelectedMonth, CONSTRAINED)), [Measures].[CALCED OT]))

MEMBER [Measures].[Overtime Hours %] AS '[Measures].[Overtime Hours] / [Measures].[Available Hours minus PTO]'
	
SELECT 
  {
    [Measures].[Employee Hours],
    [Measures].[Employee Hours %],
    [Measures].[Overtime Hours],
    [Measures].[Overtime Hours %],
    [MEasures].[Available Hours]
  } ON COLUMNS,
  NON EMPTY CROSSJOIN(
    FILTER(
IIF(@SelectedDiscipline = @SelectedDepartment,
      DESCENDANTS(StrToMember(@SelectedDiscipline, CONSTRAINED), [Employee].[DISC - DEPT - EMP].[Department], AFTER),
      DESCENDANTS(StrToMember(@SelectedDepartment, CONSTRAINED), [Employee].[DISC - DEPT - EMP].[Department], AFTER)
), 
      NOT INSTR([Employee].[Department].CurrentMember.MEMBER_NAME, "Freelance")),
    FILTER ([Employee].[Manager Name].[Manager Name].Members , 

             NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")
 
           ),

    [Employee].[Employee Bill Rate].[Employee Bill Rate].ALLMEMBERS,
    [Employee].[Employee Level].[Employee Level].ALLMEMBERS,
    {
                	-- PTO Utilization Category excluded
		-- PRODUCTION Utiltization Category included with detail
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[PRODUCTION]},
			[Employee Hours Time Category].[Time Category].[Time Category].ALLMEMBERS),
		-- ADMIN Utiltization Category rolled-up witout detail
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[ADMIN]},
			{[Employee Hours Time Category].[Time Category].[Admin]})
                   },
                   {StrToMember(@SelectedMonth, CONSTRAINED), [Time].[Year - Month].[YTD]}
          ) DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM [OLSON BI] 
CELL PROPERTIES 
  VALUE
,BACK_COLOR
,FORE_COLOR
,FORMATTED_VALUE
,FORMAT_STRING
,FONT_NAME
,FONT_SIZE
,FONT_FLAGS;

Free Windows Admin Tool Kit Click here and download it now
July 11th, 2013 7:47am

Made some progress...!

The first query works great - it's the second one that is still giving me issues.

Here is the query in question:

WITH 

MEMBER [Time].[Year - Month].[YTD] AS AGGREGATE(YTD(StrToMember(@SelectedMonth, CONSTRAINED)))

SET [SelectedDiscipline] AS StrToMember(@SelectedDiscipline, CONSTRAINED)
SET [SelectedDepartment] AS StrToMember(@SelectedDepartment, CONSTRAINED)

MEMBER [Employee].[Department].[Non-Freelance] AS 
  AGGREGATE(
    FILTER(
      IIF(@SelectedDiscipline = @SelectedDepartment, 
        DESCENDANTS([SelectedDiscipline], [Employee].[DISC - DEPT - EMP].[Department], SELF), 
        DESCENDANTS([SelectedDepartment], [Employee].[DISC - DEPT - EMP].[Department], SELF)),
        NOT INSTR([Employee].[DISC - DEPT - EMP].CurrentMember.MEMBER_NAME, "Freelance")))



MEMBER [Measures].[Overtime Hours Calc] AS 
  SUM(
    DESCENDANTS(
      IIF(@SelectedDiscipline = @SelectedDepartment, 
        STRTOMEMBER(@SelectedDiscipline, CONSTRAINED), 
        STRTOMEMBER(@SelectedDepartment, CONSTRAINED)), 
      [Employee].[DISC - DEPT - EMP].[DEPARTMENT], 
      AFTER),
    [Measures].[Employee Overtime Hours])	

--< We need to OT over the individual months in YTD >--
MEMBER [Measures].[Overtime Hours] AS Measures.[CALCED OT]


MEMBER [Measures].[Overtime Hours %] AS '[Measures].[Overtime Hours] / [Measures].[Available Hours minus PTO]'	

SELECT 
  { 
    [Measures].[Employee Hours],
    [Measures].[Employee Hours %],
    [Measures].[Overtime Hours],
    [Measures].[Overtime Hours %],
    [Measures].[Available Hours minus PTO]
  } 
ON COLUMNS,
               -- CROSSJOIN (FILTER([Employee].[Manager Name].[Manager Name].Members, 
               --    NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")),
	   CROSSJOIN(FILTER([Employee].[Employee Level].AllMembers, CInt([Employee].[Employee Level].CurrentMember.MEMBER_KEY) >= 1),
                
               --   CROSSJOIN (FILTER([Employee].[Manager Name].[Manager Name].Members, 
               --   NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")),
	
CROSSJOIN(
		{[Employee].[Department].[Non-Freelance]},
		{
		-- PTO Utilization Category excluded 
		-- ADMIN Utiltization Category rolled-up witout detail 
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[ADMIN]},
			{[Employee Hours Time Category].[Time Category].[Admin]}),
		-- PRODUCTION Utiltization Category included with detail 
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[PRODUCTION]},
			[Employee Hours Time Category].[Time Category].[Time Category].ALLMEMBERS)
		},
		{StrToMember(@SelectedMonth, CONSTRAINED), [Time].[Year - Month].[YTD]}))
	DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM [OLSON BI]
CELL PROPERTIES 
  VALUE
 ,BACK_COLOR
 ,FORE_COLOR
 ,FORMATTED_VALUE
 ,FORMAT_STRING
 ,FONT_NAME
 ,FONT_SIZE
 ,FONT_FLAGS;

I need to apply the same filter in this query as in the initial one.

As you can see, I inserted a CROSSJOIN with a FILTER. This partially works. While the hours reflect the correct value (excluding employees with an 'O-Tern') manager name, the Employee Hours % column is now completely empty. Here are two screen shots - one before I added the filter and one after:

As you can see the hours for Level 7 have been reduced - which is the correct behavior. But now none of the percentages are appearing, except for Levels 1 and 7.

I'm pretty sure it's something to do with the new CROSSJOIN/FILTER I introduced.

Is there an easier way to get the filtering I'm looking for without having to resort to doing a CROSSJOIN/FILTER?

Can I do a simple "WHERE MANAGER NAME NOT LIKE blah blah blah"?? 

Or at least wedge in a simplified FILTER statement?

 

July 11th, 2013 11:40pm

Hi

Added FILTER to second query, try it once

WITH 

MEMBER [Time].[Year - Month].[YTD] AS AGGREGATE(YTD(StrToMember(@SelectedMonth, CONSTRAINED)))

SET [SelectedDiscipline] AS StrToMember(@SelectedDiscipline, CONSTRAINED)
SET [SelectedDepartment] AS StrToMember(@SelectedDepartment, CONSTRAINED)

MEMBER [Employee].[Department].[Non-Freelance] AS 
  AGGREGATE(
    FILTER(
      IIF(@SelectedDiscipline = @SelectedDepartment, 
        DESCENDANTS([SelectedDiscipline], [Employee].[DISC - DEPT - EMP].[Department], SELF), 
        DESCENDANTS([SelectedDepartment], [Employee].[DISC - DEPT - EMP].[Department], SELF)),
        NOT INSTR([Employee].[DISC - DEPT - EMP].CurrentMember.MEMBER_NAME, "Freelance")))



MEMBER [Measures].[Overtime Hours Calc] AS 
  SUM(
    DESCENDANTS(
      IIF(@SelectedDiscipline = @SelectedDepartment, 
        STRTOMEMBER(@SelectedDiscipline, CONSTRAINED), 
        STRTOMEMBER(@SelectedDepartment, CONSTRAINED)), 
      [Employee].[DISC - DEPT - EMP].[DEPARTMENT], 
      AFTER),
    [Measures].[Employee Overtime Hours])	

--< We need to OT over the individual months in YTD >--
MEMBER [Measures].[Overtime Hours] AS Measures.[CALCED OT]


MEMBER [Measures].[Overtime Hours %] AS '[Measures].[Overtime Hours] / [Measures].[Available Hours minus PTO]'	

SELECT 
  { 
    [Measures].[Employee Hours],
    [Measures].[Employee Hours %],
    [Measures].[Overtime Hours],
    [Measures].[Overtime Hours %],
    [Measures].[Available Hours minus PTO]
  } 
ON COLUMNS,
             
	   CROSSJOIN(
               FILTER([Employee].[Employee Level].AllMembers, CInt([Employee].[Employee Level].CurrentMember.MEMBER_KEY) >= 1)),
                
               FILTER([Employee].[Manager Name].[Manager Name].Members, NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern"))),
	
CROSSJOIN(
		{[Employee].[Department].[Non-Freelance]},
		{
		-- PTO Utilization Category excluded 
		-- ADMIN Utiltization Category rolled-up witout detail 
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[ADMIN]},
			{[Employee Hours Time Category].[Time Category].[Admin]}),
		-- PRODUCTION Utiltization Category included with detail 
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[PRODUCTION]},
			[Employee Hours Time Category].[Time Category].[Time Category].ALLMEMBERS)
		},
		{StrToMember(@SelectedMonth, CONSTRAINED), [Time].[Year - Month].[YTD]}))
	DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM [OLSON BI]
CELL PROPERTIES 
  VALUE
 ,BACK_COLOR
 ,FORE_COLOR
 ,FORMATTED_VALUE
 ,FORMAT_STRING
 ,FONT_NAME
 ,FONT_SIZE
 ,FONT_FLAGS;

1. We can use WHERE clause to filter the members

2. We can also use SubCube to Filter the Cube to required Managers information

See you how you go with it

Free Windows Admin Tool Kit Click here and download it now
July 12th, 2013 1:15am

Thanks again!!

I tried your query ver batim and got the following:

It seems to be something with the new FILTER. I've tried a few different permutations but keeps goofing up.

So if this can't be fixed, how would a WHERE clause fit in?

July 12th, 2013 5:05am

Hi

I think, it got some typo with ending but can try this

WITH 

MEMBER [Time].[Year - Month].[YTD] AS AGGREGATE(YTD(StrToMember(@SelectedMonth, CONSTRAINED)))

SET [SelectedDiscipline] AS StrToMember(@SelectedDiscipline, CONSTRAINED)
SET [SelectedDepartment] AS StrToMember(@SelectedDepartment, CONSTRAINED)

MEMBER [Employee].[Department].[Non-Freelance] AS 
  AGGREGATE(
    FILTER(
      IIF(@SelectedDiscipline = @SelectedDepartment, 
        DESCENDANTS([SelectedDiscipline], [Employee].[DISC - DEPT - EMP].[Department], SELF), 
        DESCENDANTS([SelectedDepartment], [Employee].[DISC - DEPT - EMP].[Department], SELF)),
        NOT INSTR([Employee].[DISC - DEPT - EMP].CurrentMember.MEMBER_NAME, "Freelance")))



MEMBER [Measures].[Overtime Hours Calc] AS 
  SUM(
    DESCENDANTS(
      IIF(@SelectedDiscipline = @SelectedDepartment, 
        STRTOMEMBER(@SelectedDiscipline, CONSTRAINED), 
        STRTOMEMBER(@SelectedDepartment, CONSTRAINED)), 
      [Employee].[DISC - DEPT - EMP].[DEPARTMENT], 
      AFTER),
    [Measures].[Employee Overtime Hours])	

--< We need to OT over the individual months in YTD >--
MEMBER [Measures].[Overtime Hours] AS Measures.[CALCED OT]


MEMBER [Measures].[Overtime Hours %] AS '[Measures].[Overtime Hours] / [Measures].[Available Hours minus PTO]'	

SELECT 
  { 
    [Measures].[Employee Hours],
    [Measures].[Employee Hours %],
    [Measures].[Overtime Hours],
    [Measures].[Overtime Hours %],
    [Measures].[Available Hours minus PTO]
  } 
ON COLUMNS,
               -- CROSSJOIN (FILTER([Employee].[Manager Name].[Manager Name].Members, 
               --    NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")),
	   CROSSJOIN(FILTER([Employee].[Employee Level].AllMembers, CInt([Employee].[Employee Level].CurrentMember.MEMBER_KEY) >= 1),
                
               --   CROSSJOIN (FILTER([Employee].[Manager Name].[Manager Name].Members, 
               --   NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")),

	
CROSSJOIN(
		{[Employee].[Department].[Non-Freelance]},
		{
		-- PTO Utilization Category excluded 
		-- ADMIN Utiltization Category rolled-up witout detail 
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[ADMIN]},
			{[Employee Hours Time Category].[Time Category].[Admin]}),
		-- PRODUCTION Utiltization Category included with detail 
		CROSSJOIN(
			{[Employee Hours Time Category].[Utilization Category].[Utilization Category].&[PRODUCTION]},
			[Employee Hours Time Category].[Time Category].[Time Category].ALLMEMBERS)
		},
		{StrToMember(@SelectedMonth, CONSTRAINED), [Time].[Year - Month].[YTD]}))
	DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM 
 ( SELECT FILTER([Employee].[Manager Name].[Manager Name].Members, NOT InStr([Employee].[Manager Name].CurrentMember.MEMBER_NAME, "O-Tern")) ON COLUMNS FROM
   [OLSON BI]
 )
CELL PROPERTIES 
  VALUE
 ,BACK_COLOR
 ,FORE_COLOR
 ,FORMATTED_VALUE
 ,FORMAT_STRING
 ,FONT_NAME
 ,FONT_SIZE
 ,FONT_FLAGS;

Let me know the results
Free Windows Admin Tool Kit Click here and download it now
July 12th, 2013 5:25am

Prav:

A thousand thank you's!!

So, if I understand what you did correctly, the CROSSJOIN select got me all the results that match the criteris, and then I FILTER on that "big" result set.

It's like a SELECT in SQL that uses JOINS and then has a WHERE clause after the FROM.

Did I get that right?

Thanks!!

July 13th, 2013 7:52am

I like it too. I get my first result.
Free Windows Admin Tool Kit Click here and download it now
July 13th, 2013 7:34pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics