Проблема, с которой вы сталкиваетесь, связана с тем, что вы удаляете столбцы внутри своего диапазона цикла. Когда вы удаляете столбец, диапазон, который вы циклически изменяете, приводит к пропуску столбцов (в соответствии с вашими результатами). Чтобы бороться с этим, вы можете использовать метод Union
, который позволяет удалять столбцы вне цикла, чтобы вы не столкнулись с сообщенной проблемой. В нижнем решении показано, как исправить сообщенную проблему, если вы решили удалить столбцы внутри цикла.
Select Case
. Прокрутите диапазон и, если ячейка отсутствует в списке в первом случае, она будет помечена для удаления во втором случае (Case Else
).
После того, как вы зациклили свои заголовки, удалите все столбцы сразу, что означает, что во время зацикливания смещения диапазона не будет.
Sub DeleteColumns()
Dim iCell As Range, DeleteMe As Range
For Each iCell In Range("A1:W1")
Select Case iCell
Case "Cartons", "ShipVia", "Name", "Address", "City", "State", "Zip"
'Do Nothing
Case Else
If Not DeleteMe Is Nothing Then
Set DeleteMe = Union(DeleteMe, iCell)
Else
Set DeleteMe = iCell
End If
End Select
Next iCell
If Not DeleteMe Is Nothing Then DeleteMe.EntireColumn.Delete
End Sub
Вы также можете перебирать массив. Обратите внимание, что цикл столбца движется в обратном направлении, чтобы остановить смещение соответствующего диапазона внутри цикла (ваша первоначальная проблема). Для этого вам нужно сбросить цикл For Each
и переключиться на For j = # - #
, чтобы вы могли использовать свойство Step -1
Sub Array_Method()
Dim Arr: Arr = Array("Cartons", "ShipVia", "Name", "Address", "City", "State", "Zip")
Dim i As Long, j As Long
For j = 23 To 1 Step -1
For i = UBound(Arr) To LBound(Arr)
If Arr(i) = Cells(1, j) Then
Cells(1, j).EntireColumn.Delete
End If
Next i
Next j
End Sub
Я использовал бы Windows встроенные интернет-способности времени. Можно настроить сервер времени на сервере, иметь его, получают время от 2-го уровневого сервера времени и имеют все клиентские машины, получают время от него.
Я снизился на application-setting-system-time дорогу прежде.
Это - вызов API Win32 установки системного времени:
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME {
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
}
[DllImport("kernel32.dll", SetLastError=true)]
public static extern bool SetSystemTime(ref SYSTEMTIME theDateTime );
Я не абсолютно уверен, как Вы разработали бы безопасность, таким образом, что Вы могли выполнить ту функцию на клиенте, все же.
Можно получить намного больше детали об установке системного времени в PInvoke.
Вы могли также, вероятно, сделать это в пакетном файле с помощью некоторой комбинации
TIME
установить время, и
net time \\server_name
получать время с сервера.
Способом запросить сетевую машину, поскольку это - системное время, является NetRemoteTOD.
Вот код, чтобы сделать это в Delphi (пример использования отправляется ниже).
Так как это полагается на Windows API calls, это не должно слишком отличаться в C#.
unit TimeHandler;
interface
type
TTimeHandler = class
private
FServerName : widestring;
public
constructor Create(servername : widestring);
function RemoteSystemTime : TDateTime;
procedure SetLocalSystemTime(settotime : TDateTime);
end;
implementation
uses
Windows, SysUtils, Messages;
function NetRemoteTOD(ServerName :PWideChar; var buffer :pointer) : integer; stdcall; external 'netapi32.dll';
function NetApiBufferFree(buffer : Pointer) : integer; stdcall; external 'netapi32.dll';
type
//See MSDN documentation on the TIME_OF_DAY_INFO structure.
PTime_Of_Day_Info = ^TTime_Of_Day_Info;
TTime_Of_Day_Info = record
ElapsedDate : integer;
Milliseconds : integer;
Hours : integer;
Minutes : integer;
Seconds : integer;
HundredthsOfSeconds : integer;
TimeZone : LongInt;
TimeInterval : integer;
Day : integer;
Month : integer;
Year : integer;
DayOfWeek : integer;
end;
constructor TTimeHandler.Create(servername: widestring);
begin
inherited Create;
FServerName := servername;
end;
function TTimeHandler.RemoteSystemTime: TDateTime;
var
Buffer : pointer;
Rek : PTime_Of_Day_Info;
DateOnly, TimeOnly : TDateTime;
timezone : integer;
begin
//if the call is successful...
if 0 = NetRemoteTOD(PWideChar(FServerName),Buffer) then begin
//store the time of day info in our special buffer structure
Rek := PTime_Of_Day_Info(Buffer);
//windows time is in GMT, so we adjust for our current time zone
if Rek.TimeZone <> -1 then
timezone := Rek.TimeZone div 60
else
timezone := 0;
//decode the date from integers into TDateTimes
//assume zero milliseconds
try
DateOnly := EncodeDate(Rek.Year,Rek.Month,Rek.Day);
TimeOnly := EncodeTime(Rek.Hours,Rek.Minutes,Rek.Seconds,0);
except on e : exception do
raise Exception.Create(
'Date retrieved from server, but it was invalid!' +
#13#10 +
e.Message
);
end;
//translate the time into a TDateTime
//apply any time zone adjustment and return the result
Result := DateOnly + TimeOnly - (timezone / 24);
end //if call was successful
else begin
raise Exception.Create('Time retrieval failed from "'+FServerName+'"');
end;
//free the data structure we created
NetApiBufferFree(Buffer);
end;
procedure TTimeHandler.SetLocalSystemTime(settotime: TDateTime);
var
SystemTime : TSystemTime;
begin
DateTimeToSystemTime(settotime,SystemTime);
SetLocalTime(SystemTime);
//tell windows that the time changed
PostMessage(HWND_BROADCAST,WM_TIMECHANGE,0,0);
end;
И вот пример использования:
procedure TfrmMain.SynchLocalTimeWithServer;
var
tod : TTimeHandler;
begin
tod := TTimeHandler.Create(cboServerName.Text);
try
tod.SetLocalSystemTime(tod.RemoteSystemTime);
finally
FreeAndNil(tod);
end; //try-finally
end;